sql 一对多查询

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sql 一对多查询相关的知识,希望对你有一定的参考价值。

现有2个表:
学生表:Student表(StudentId,StudentName)
成绩表:Results表(StudentId,Chinese,Math)

两表是1对多的关系,一个学生有多个成绩
问题:
显示2表的信息,用一个sql语句写出来,应该怎么写啊?

例:
学生表
StudentId StudentName
1 尹智杰
2 宋娜
3 长峰

成绩表
StudentId Subject Math
1 语文 100
1 数学 90
2 英语 85
2 物理 99
2 化学 88
2 地理 78
3 语文 99

想结果显示如下:
1 尹智杰 语文 100 数学 90
2 宋娜 英语 85 物理 99 化学 88 地理 78
3 长峰 语文 99

问题:显示每个学生的所有成绩,并且必须是一条记录显示
sql 语句应该怎样写????

交给我吧,典型的交叉查询,行列转换
select s.StudentName,
(case r.Subject when '语文' then r.Math end) as 语文,
(case r.Subject when '数学' then r.Math end) as 数学,
(case r.Subject when '英语' then r.Math end) as 英语,
(case r.Subject when '物理' then r.Math end) as 物理,
(case r.Subject when '地理' then r.Math end) as 地理
from Student s,Results r
where s.StudentId=r.StudentId

能用的话记得给分哦~追问

首先非常的感谢,科目是动态的 你这样应该是不行的吧

追答

动态的要涉及到PL/SQL的函数调用了……那就不是简单SQL语句了

参考技术A http://hi.baidu.com/xckouy/blog/item/acb9196b010f60e142169409.html 方法二
http://hi.baidu.com/xckouy/blog/item/59f80adb342eaec38c10293f.html
处理多行转一行,使用动态会更简单点!
--参照下列处理成绩表(可以有问题),再联合学生表查询
SELECT
B.StudentId,
LEFT(UserList,LEN(UserList)-1) as paths
FROM
(
SELECT
StudentId,
(
SELECT
Subject +',' +Math
FROM
Results
WHERE
StudentId= A.StudentId
ORDER BY
StudentId FOR XML PATH('')
) AS UserList
FROM
Results A
GROUP BY
StudentId
)
B本回答被提问者采纳
参考技术B 数据库表本身设计不合理
要求的表也不合理

另外你的成绩表前后是不是不一致?

MyBatis总结之高级映射一对多查询

上一篇博文总结了一下一对一的映射,本文主要总结一下一对多的映射,订单项和订单明细是一对多的关系,所以本文主要来查询订单表,然后关联订单明细表,这样就有一对多的问题出来了。

  首先还是先写sql语句,在写sql语句的时候遵循两点:

 

查询的主表是哪个? 订单表

查询的关联表是哪个? 订单明细表

  明确了主表和关联表,下面就可以写sql了,我们在上一节的sql基础上添加订单明细表的关联即可。

 

SELECT

  orders.*,

  user.`username`,

  user.`sex`,

  user.`address`,

  orderdetail.`id` orderdetail_id,

  orderdetail.`items_id`,

  orderdetail.`items_num`,

  orderdetail.`orders_id`

FROM

  orders,

  USER,

  orderdetail

WHERE orders.`user_id`=user.`id` AND orders.`id` = orderdetail.`orders_id`

  这样我们就查询出了订单表中的所有字段,user表和orderdetail表的部分字段,当然也可以查询所有字段,这个根据具体需求来定。

  从结果中可以看出,订单的信息有重复,订单项是不重复的,因为一对多嘛,这很好理解。所以如果我们用resultType来做映射的话就会出现订单信息的重复,我们不希望出现这个结果,即对orders的映射不能出现重复记录的情况。那么我们就需要在Orders.java类中添加一个List<OrderDetail> orderDetails属性来封装订单明细项(比较简单,代码就不贴了),最终会将订单信息映射到Orders中,该订单所对应的订单明细映射到Orders中的orderDetails属性中(这跟hibernate中有点类似,如果是hibernate,也会在Orders类中维护一个装OrderDetailList)。

  有了这个思路,接下来就开始写映射文件了。

 

<select id="findOrdersAndOrderDetailResultMap" resultMap="OrdersAndOrderDetailResultMap">

    SELECT

      orders.*,

      user.`username`,

      user.`sex`,

      user.`address`,

      orderdetail.`id` orderdetail_id,

      orderdetail.`items_id`,

      orderdetail.`items_num`,

      orderdetail.`orders_id`

    FROM

      orders,

      USER,

      orderdetail

    WHERE orders.`user_id`=user.`id` AND orders.`id` = orderdetail.`orders_id`

</select>

 

  所以我们要定义一个名为OrdersAndOrderDetailResultMapresultMap,如下:

 

<resultMap type="mybatis.po.Orders" id="OrdersAndOrderDetailResultMap" extends="OrdersUserResultMap">

    <!-- 配置映射订单信息和关联的用户信息和上面的一样,继承上面的即可 -->

    <!-- 配置关联的订单明细信息 -->

    <collection property="orderdetails" ofType="mybatis.po.Orderdetail">

        <id column="orderdetail_id" property="id"/>

        <result column="items_id" property="itemsId"/>

        <result column="items_num" property="itemsNum"/>

        <result column="orders_id" property="ordersId"/>

    </collection>

</resultMap>

 

  这里看到了一个继承,因为订单信息和关联的用户信息和前面一对一是完全一样的,我们就不需要再写一遍了,<resultMap>支持继承,直接继承那个resultMap即可,然后加上订单明细这部分即可。

  <collection>是用来处理一对多映射的标签,property属性是Orders.java类中对应的装OrderDetailList的属性名,就是刚刚定义的那个ListofType属性表示该List中装的是啥,可以是完全限定名,也可以是别名。然后<collection>里面的标签和属性就和前面一样了,不再赘述。

  然后定义一下mapper接口即可:

 

public interface UserMapperOrders {

 

    //查询订单(关联用户)及订单明细

    public List<Orders> findOrdersAndOrderDetailResultMap() throws Exception;

 

}

 

以上是关于sql 一对多查询的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis高级篇 - 关联查询(一对多)

MyBatis总结之高级映射一对多查询

MyBatis关于多表联查 关联关系之一--------一对多(单条sql语句查询)

mybatis的动态sql编写以及一对一关系查询和一对多的查询

sql一对多的查询代码怎么查?

MyBatis学习09高级映射之一对多查询