MySQL 取A表有的B表没有的(A表排除B表)

文章介绍了在MySQL中使用左连接、NOTEXISTS和NOTIN操作来查询A表中plant=5的数据,同时排除B表中已存在的记录。作者给出了详细步骤和示例,以实现A表独有的数据筛选。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有三种方法

1、用左连接,取连接后b的id为null

select *
from A left join B on A.id = b.id
where B.id is null
;

2、 (NOT)EXIST

select *
from A
where not exists (select * from B where A.id = B.id)
;

3、 (NOT) IN


select *
from A
where A.id not in (select id from B)

题目:数据库表如下,例如id=x,plant=5,那么后面plant=4的数据在查询时并不查询,只选择plant=5的数据,如果x中plant没有等于5的数据,那么plant=4的数据要全部查询,同理y也是这样,有5的就选择5,4不做查询,没有5就查询4.

题解:

1、将这个表划分成plant=5和plant=4两个表

SELECT *from test where plant=5

SELECT *from test where plant=4

2、将上面两个表进行合并,如果两张表的id相等意味着plant=5已经存在,那么后面的表的数据就是不需要查询的数据,现在将不需要查询的数据获取到,不理解的话可以从where那里去掉看一下合并的表,在理解一下

SELECT  b.* from (SELECT *from test where plant=5) a ,(SELECT *from test where plant=4) b WHERE a.id=b.id GROUP BY id,plant,address

3、到这里就是这个文章标题的问题了,取A表有的B表没有的,上述面写的sql语句代表就是b表,这里选择前面讲的方式二进行解题

select *
from test a
where not exists (select * from (SELECT  b.* from (SELECT *from test where plant=5) a ,(SELECT *from test where plant=4) b WHERE a.id=b.id GROUP BY id,plant,address) B where A.id = B.id and A.plant=B.plant AND A.address =B.address )

参考文章:mysql查找不同数据(A表排除B表)_sql a表剔除b表中有的记录-优快云博客

<think>嗯,用户的问题是关于如何从B中查询每个学生的最新成绩记录。我需要仔细分析这个问题,并确保给出的解决方案是正确的。 首先,用户提到的是“仅有的B”,所以所有需要的信息都应该在这张中。我需要确定B的结构,可能包含学生ID、学科、成绩、考试时间等字段。假设结构中有学生ID(student_id)、成绩(score)、考试时间(exam_date)这些关键字段。 接下来,用户需要每个学生的最新成绩。这里的关键点在于“每个学生”和“最新”。这意味着需要对每个学生分组,然后在每个组内找到最新的记录。通常,最新记录可以通过最大的考试日期(exam_date)来确定,或者如果有自增的时间戳字段也可以使用。 常见的解决方法是使用窗口函数,比如ROW_NUMBER(),按学生分组并按考试日期降序排序,然后第一条记录。这种方法在支持窗口函数的数据库(如MySQL 8.0+、PostgreSQL、SQL Server)中有效。例如: SELECT student_id, score, exam_date FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY student_id ORDER BY exam_date DESC) as rn FROM B ) t WHERE rn = 1; 如果数据库不支持窗口函数,可能需要使用子查询来找到每个学生的最大考试日期,然后与原连接。例如: SELECT B.student_id, B.score, B.exam_date FROM B INNER JOIN ( SELECT student_id, MAX(exam_date) as max_date FROM B GROUP BY student_id ) t ON B.student_id = t.student_id AND B.exam_date = t.max_date; 但需要注意,如果有多个记录在同一学生和同一最大日期下,这种方法会返回所有记录,可能需要进一步处理。 另外,用户可能还希望处理并列情况,比如同一学生有多个相同的最新日期,这时候可能需要根据需求选择所有记录或只一条。使用ROW_NUMBER()可以确保只一条,而使用RANK()则会返回所有并列的记录。 还需要考虑性能问题,尤其是在数据量大的情况下。窗口函数通常效率较高,但具体性能决于数据库的优化情况。 最后,需要验证解决方案是否正确。例如,假设有一个学生的多个成绩记录,其中最新的日期是2023-10-01,那么查询应该只返回该日期对应的记录。如果存在多个相同日期的记录,是否都需要显示?这时候用户的需求可能需要进一步明确,但在问题中用户提到“最新成绩记录”,可能指的是每个学生一条最新记录,所以使用ROW_NUMBER()更合适。 总结来说,解决方案应该根据数据库的支持情况选择合适的方法,确保正确性和效率,并处理可能的重复情况。</think>### 解决方案:查询每个学生的最新成绩记录 假设$B$的结构包含以下关键字段: - $student\_id$(学生ID) - $score$(成绩) - $exam\_date$(考试日期) #### 方法1:使用窗口函数(推荐) 适用于支持窗口函数的数据库(如MySQL 8.0+、PostgreSQL、SQL Server): ```sql SELECT student_id, score, exam_date FROM ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY student_id ORDER BY exam_date DESC ) as rn FROM B ) t WHERE rn = 1; ``` - $ROW\_NUMBER()$按学生分组,按考试日期降序排序,第一条记录[^4] - 若存在同一学生多条相同日期的记录,仅返回一条 #### 方法2:子查询+连接 适用于所有SQL数据库: ```sql SELECT B.student_id, B.score, B.exam_date FROM B INNER JOIN ( SELECT student_id, MAX(exam_date) as max_date FROM B GROUP BY student_id ) t ON B.student_id = t.student_id AND B.exam_date = t.max_date; ``` - 先查询每个学生的最大考试日期,再关联原完整记录[^2] - 可能返回多条记录(若同一学生有多个相同最大日期的成绩) #### 方法3:LEFT JOIN去重 ```sql SELECT B1.* FROM B B1 LEFT JOIN B B2 ON B1.student_id = B2.student_id AND B1.exam_date < B2.exam_date WHERE B2.student_id IS NULL; ``` - 通过左连接排除非最新记录 - 兼容性较好,但性能可能较差 --- ### 关键逻辑说明 1. **分组依据**:按$student\_id$分组,保证每个学生独立处理 2. **排序条件**:用$exam\_date$ DESC确定最新记录 3. **去重策略**:窗口函数效率最高,子查询方法需注意重复数据[^1]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值