经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MS SQL Server » 查看文章
学习记录--查询没有学全所有课的同学的学号、姓名、以及未学科目
来源:cnblogs  作者:Simona'  时间:2019/6/4 17:47:53  对本文有异议

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

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

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

  1. CREATE TABLE [dbo].[课程表](
  2. 课程id [INT] NULL,
  3. 课程名称 [NVARCHAR](50) NULL,
  4. 讲师id [INT] NULL
  5. ) ON [PRIMARY]
  6.  
  7. CREATE TABLE [dbo].成绩表(
  8. 成绩id [int] NULL,
  9. 课程id [int] NULL,
  10. 成绩 [int] NULL
  11. ) ON [PRIMARY]
  12.  
  13. CREATE TABLE [dbo].学生表(
  14. 学生id [int] NULL,
  15. 学生名称 [nvarchar](50) NULL,
  16. 年龄 [int] NULL,
  17. 性别 [nvarchar](50) NULL
  18. ) ON [PRIMARY]
  19.  
  20.  
  21. CREATE TABLE [dbo].讲师表(
  22. 讲师id [int] NULL,
  23. 讲师名称 [nvarchar](50) NULL
  24. ) ON [PRIMARY]
  25.  
  26.  
  27. INSERT [dbo].[成绩表] ([成绩id], [课程id], [成绩]) VALUES (1, 1, 20)
  28. GO
  29. INSERT [dbo].[成绩表] ([成绩id], [课程id], [成绩]) VALUES (1, 2, 20)
  30. GO
  31. INSERT [dbo].[成绩表] ([成绩id], [课程id], [成绩]) VALUES (1, 3, 20)
  32. GO
  33. INSERT [dbo].[成绩表] ([成绩id], [课程id], [成绩]) VALUES (2, 1, 20)
  34. GO
  35. INSERT [dbo].[成绩表] ([成绩id], [课程id], [成绩]) VALUES (2, 2, 20)
  36. GO
  37. INSERT [dbo].[成绩表] ([成绩id], [课程id], [成绩]) VALUES (3, 3, 20)
  38. GO
  39.  
  40.  
  41. INSERT [dbo].[讲师表] ([讲师id], [讲师名称]) VALUES (1, N'张老师')
  42. GO
  43. INSERT [dbo].[讲师表] ([讲师id], [讲师名称]) VALUES (2, N'李老师')
  44. GO
  45. INSERT [dbo].[讲师表] ([讲师id], [讲师名称]) VALUES (3, N'王老师')
  46. GO
  47. INSERT [dbo].[讲师表] ([讲师id], [讲师名称]) VALUES (4, N'宋老师')
  48. GO
  49.  
  50. INSERT [dbo].[课程表] ([课程id], [课程名称], [讲师id]) VALUES (1, N'语文', 1)
  51. GO
  52. INSERT [dbo].[课程表] ([课程id], [课程名称], [讲师id]) VALUES (2, N'数学', 2)
  53. GO
  54. INSERT [dbo].[课程表] ([课程id], [课程名称], [讲师id]) VALUES (3, N'英语', 3)
  55. GO
  56. INSERT [dbo].[课程表] ([课程id], [课程名称], [讲师id]) VALUES (4, N'体育', 4)
  57. GO
  58.  
  59. INSERT [dbo].[学生表] ([学生id], [学生名称], [年龄], [性别]) VALUES (1, N'张三', 12, N'')
  60. GO
  61. INSERT [dbo].[学生表] ([学生id], [学生名称], [年龄], [性别]) VALUES (2, N'李四', 12, N'')
  62. GO
  63. INSERT [dbo].[学生表] ([学生id], [学生名称], [年龄], [性别]) VALUES (3, N'王五', 12, N'')
  64. GO
  65. INSERT [dbo].[学生表] ([学生id], [学生名称], [年龄], [性别]) VALUES (4, N'赵六', 12, N'')

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

  1. SELECT s.学生id,
  2. s.学生名称,
  3. s.年龄,
  4. s.性别,
  5. c.课程id,
  6. c.课程名称,
  7. c.讲师id
  8. FROM dbo.学生表 s
  9. LEFT JOIN dbo.课程表 c ON 1=1
  10. LEFT JOIN dbo.成绩表 ON s.学生id = dbo.成绩表.学生id AND 成绩表.课程id = c.课程id
  11. WHERE dbo.成绩表.学生id IS NULL

得到的结果:

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

  1. SELECT B.学生id,
  2. B.学生名称,
  3. B.年龄,
  4. LEFT(B.未学科目, LEN(B.未学科目) - 1) AS 未学科目
  5. FROM ( SELECT A.学生id,
  6. A.学生名称,
  7. A.年龄,
  8. ( SELECT Z.课程名称 + ','
  9. FROM ( SELECT s.学生id,
  10. s.学生名称,
  11. s.年龄,
  12. s.性别,
  13. c.课程id,
  14. c.课程名称,
  15. c.讲师id
  16. FROM dbo.学生表 s
  17. LEFT JOIN dbo.课程表 c
  18. ON 1 = 1
  19. LEFT JOIN dbo.成绩表
  20. ON s.学生id = dbo.成绩表.学生id
  21. AND 成绩表.课程id = c.课程id
  22. WHERE dbo.成绩表.学生id IS NULL) Z
  23. WHERE Z.学生id = A.学生id
  24. FOR XML PATH('')) AS 未学科目
  25. FROM ( SELECT s.学生id,
  26. s.学生名称,
  27. s.年龄,
  28. s.性别,
  29. c.课程id,
  30. c.课程名称,
  31. c.讲师id
  32. FROM dbo.学生表 s
  33. LEFT JOIN dbo.课程表 c
  34. ON 1 = 1
  35. LEFT JOIN dbo.成绩表
  36. ON s.学生id = dbo.成绩表.学生id
  37. AND 成绩表.课程id = c.课程id
  38. WHERE dbo.成绩表.学生id IS NULL) A
  39. GROUP BY A.学生id,
  40. A.学生名称,
  41. A.年龄,
  42. A.性别) AS B;

最后结果

 

 

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

 

原文链接:http://www.cnblogs.com/Metor9527/p/10974109.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号