欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

学习记录--查询没有学全所有课的同学的学号、姓名、以及未学科目

程序员文章站 2022-03-29 14:24:17
逛贴吧的时候遇到了这样一个问题 这样的表结构需要【查询没有学全所有课的同学的学号、姓名、以及未学科目】 脚本 解决问题,想法是【构造笛卡尔积】,然后通过【左连接】选出【成绩表】中不存在的【学生id】 得到的结果: 接下来,我用的是SQLServer,所以使用【for xml】来构造 最后结果 问题是 ......

逛贴吧的时候遇到了这样一个问题

学习记录--查询没有学全所有课的同学的学号、姓名、以及未学科目

这样的表结构需要【查询没有学全所有课的同学的学号、姓名、以及未学科目】

------------脚本-------------------------

create table [dbo].[课程表](
    课程id [int] null,
    课程名称 [nvarchar](50) null,
    讲师id [int] null
) on [primary]

create table [dbo].成绩表(
    成绩id [int] null,
    课程id [int] null,
    成绩 [int] null
) on [primary]

create table [dbo].学生表(
    学生id [int] null,
    学生名称 [nvarchar](50) null,
    年龄 [int] null,
    性别 [nvarchar](50) null
) on [primary]


create table [dbo].讲师表(
    讲师id [int] null,
    讲师名称 [nvarchar](50) null
) on [primary]


insert [dbo].[成绩表] ([成绩id], [课程id], [成绩]) values (1, 1, 20)
go
insert [dbo].[成绩表] ([成绩id], [课程id], [成绩]) values (1, 2, 20)
go
insert [dbo].[成绩表] ([成绩id], [课程id], [成绩]) values (1, 3, 20)
go
insert [dbo].[成绩表] ([成绩id], [课程id], [成绩]) values (2, 1, 20)
go
insert [dbo].[成绩表] ([成绩id], [课程id], [成绩]) values (2, 2, 20)
go
insert [dbo].[成绩表] ([成绩id], [课程id], [成绩]) values (3, 3, 20)
go


insert [dbo].[讲师表] ([讲师id], [讲师名称]) values (1, n'张老师')
go
insert [dbo].[讲师表] ([讲师id], [讲师名称]) values (2, n'李老师')
go
insert [dbo].[讲师表] ([讲师id], [讲师名称]) values (3, n'王老师')
go
insert [dbo].[讲师表] ([讲师id], [讲师名称]) values (4, n'宋老师')
go

insert [dbo].[课程表] ([课程id], [课程名称], [讲师id]) values (1, n'语文', 1)
go
insert [dbo].[课程表] ([课程id], [课程名称], [讲师id]) values (2, n'数学', 2)
go
insert [dbo].[课程表] ([课程id], [课程名称], [讲师id]) values (3, n'英语', 3)
go
insert [dbo].[课程表] ([课程id], [课程名称], [讲师id]) values (4, n'体育', 4)
go

insert [dbo].[学生表] ([学生id], [学生名称], [年龄], [性别]) values (1, n'张三', 12, n'男')
go
insert [dbo].[学生表] ([学生id], [学生名称], [年龄], [性别]) values (2, n'李四', 12, n'男')
go
insert [dbo].[学生表] ([学生id], [学生名称], [年龄], [性别]) values (3, n'王五', 12, n'男')
go
insert [dbo].[学生表] ([学生id], [学生名称], [年龄], [性别]) values (4, n'赵六', 12, n'男')

解决问题,想法是【构造笛卡尔积】,然后通过【左连接】选出【成绩表】中不存在的【学生id】

  select    s.学生id,
            s.学生名称,
            s.年龄,
            s.性别,
            c.课程id,
            c.课程名称,
            c.讲师id
  from      dbo.学生表 s
  left join dbo.课程表 c on 1=1
  left join dbo.成绩表 on s.学生id = dbo.成绩表.学生id and 成绩表.课程id = c.课程id
  where dbo.成绩表.学生id is null

得到的结果:

学习记录--查询没有学全所有课的同学的学号、姓名、以及未学科目

接下来,我用的是sqlserver,所以使用【for xml】来构造

select b.学生id,
       b.学生名称,
       b.年龄,
       left(b.未学科目, len(b.未学科目) - 1) as 未学科目
  from (   select a.学生id,
                  a.学生名称,
                  a.年龄,
                  (   select z.课程名称 + ','
                        from (   select      s.学生id,
                                             s.学生名称,
                                             s.年龄,
                                             s.性别,
                                             c.课程id,
                                             c.课程名称,
                                             c.讲师id
                                   from      dbo.学生表 s
                                   left join dbo.课程表 c
                                     on 1        = 1
                                   left join dbo.成绩表
                                     on s.学生id   = dbo.成绩表.学生id
                                    and 成绩表.课程id = c.课程id
                                  where      dbo.成绩表.学生id is null) z
                       where z.学生id = a.学生id
                      for xml path('')) as 未学科目
             from (   select      s.学生id,
                                  s.学生名称,
                                  s.年龄,
                                  s.性别,
                                  c.课程id,
                                  c.课程名称,
                                  c.讲师id
                        from      dbo.学生表 s
                        left join dbo.课程表 c
                          on 1        = 1
                        left join dbo.成绩表
                          on s.学生id   = dbo.成绩表.学生id
                         and 成绩表.课程id = c.课程id
                       where      dbo.成绩表.学生id is null) a
            group by a.学生id,
                     a.学生名称,
                     a.年龄,
                     a.性别) as b;

最后结果

学习记录--查询没有学全所有课的同学的学号、姓名、以及未学科目

 

 

问题是解决了,但可能效率不高,毕竟笛卡尔积。