一个看似很简单的SQL却难倒了很多人

一个选课表,有学生id,课程id,老师id,要求选出同时选了语文和数学的学生

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
USE [tempschool]
GO
/****** 对象:  Table [dbo].[SelectC]    脚本日期: 07/02/2015 11:04:55 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[SelectC](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Sid] [int] NULL,
    [Cid] [int] NULL,
    [Tid] [int] NULL,
 CONSTRAINT [PK_SelectC] PRIMARY KEY CLUSTERED
(
    [ID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

插入一些模拟数据, 假设CID=1和CID=2的分别是语文和数学,那么根据下图,同时选了语文和数学的应该是1号和5号学生

 

先不要看答案,在脑子里写一个sql,然后再往下看

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

一开始得到了很多错误的答案,也是最容易出现的答案

1
2
3
4
5
--错误的答案,一条记录都找不到
select * from selectC where cid=1 and cid=2
 
--错误的答案,只选了一门语文的学生也会出现在记录中
select * from selectC where cid=1 or cid=2

  

 

 

那么正确的答案应该怎么做呢,目前我找到3种方法,

方法一:

1
2
3
select a.sid from
SelectC as a left join SelectC as b on b.sid = a.sid
where a.cid =1 and b.cid =2

  

对了,笛卡尔乘积,无限关联就可以选出同时选了语文数学英语等等等等的情况  

 

 

方法二:

1
2
3
4
5
6
SELECT sid
FROM SelectC
WHERE  (cid = 1) OR
        (cid = 2)
GROUP BY sid
HAVING (COUNT(*) >= 2)   

 这是第二种,首先先通过条件or选择出所有的语文或者数学的,然后根据sid汇总,只要count数量大于2的就是同时选择了语文和数学的,如果要扩展再多的就是修改count的数量和or的条件

 

方法三:

1
2
3
select distinct  sid from selectC where
 sid in(select sid from selectc where cid = 1)
and sid in(select sid from selectc where cid = 2)

第三种方法似乎效率就比较低了,需要用in来做查询。

 

 

不知道大家还有没有其他的写法

 

posted @   JangoJing  阅读(1667)  评论(2编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示