查询语句

1.not in

select distinct A.ID from A where A.ID not in (select ID from B)

容易理解,效率低:

2.left join

select A.ID from A left join B on A.ID=B.ID where B.ID is null

语句拆分

这条语句使用了左连接(LEFT JOIN),然后通过 WHERE B.ID is null 的条件来选择在表 A 中存在但在表 B 中不存在匹配的记录。

  • 这个查询语句可能会扫描 A 表和 B 表,然后进行连接操作并过滤出匹配条件的结果。优化器可能会根据索引情况选择合适的连接方式。
  • 这个查询语句通常能有效利用索引来进行连接和过滤,因此在合适的索引存在的情况下,性能可能较好。

3.子查询

select * from A where (select count(1) as num from B where B.ID = A.ID) = 0

语句拆分

select * from A

这是主查询的部分,意味着从表 A 中检索所有的列(使用 * 通配符)。

where(select count(1) as num from B where B.ID = A.ID) = 0

这是一个子查询,嵌套在主查询的 WHERE 子句中。

子查询使用了聚合函数 COUNT(1) 来计算匹配的记录数量,并将其作为 num 的别名返回。

  • 对表 A 中的每个记录,使用子查询检查是否在表 B 中存在匹配的记录。对于每条 A 表的记录,都会执行子查询以计算满足条件的记录数。这个查询可能会在 A 表和 B 表之间执行很多次相关子查询,导致性能较差。
  • 如果表 B 中的记录较多,或者数据量大,这种子查询方式可能会导致性能下降,特别是在没有合适索引的情况下。

如果表 A 很大,而表 B 很小,查询语句哪个更适合?

left join

原因:

  1. 左连接方式:第一个查询使用了 LEFT JOIN,它会返回表 A 中存在但在表 B 中不存在匹配的记录。由于表 B 很小,即使使用左连接,MySQL也能够迅速匹配并过滤掉与表 B 匹配的记录,以获取符合条件的结果。
  2. 利用索引:如果在表 A 和表 B 的 ID 字段上都有合适的索引,左连接操作通常能够利用这些索引,以较快的速度找到匹配和不匹配的记录,然后根据条件进行过滤。
  3. 子查询性能问题:当查询中使用了子查询,对于每个表 A 的记录都会执行一个相关子查询,这可能导致性能下降,特别是当表 A 很大时。即使表 B 很小,但是对于大型的表 A,多次执行相关子查询可能会消耗更多资源和时间。

例子

用户表[user]
会员表[member]
流程:
用户[user]激活的时候创建对应的会员[member],这样就能把会员和用户关联起来,其中关联的外建就是userId
查询:
查询用户已经激活,但是还没有创建会员的用户: in[user] & not in[member]
语句:
                    SELECT
                        u.*
                    FROM
                        user u
                    WHERE
                    u.activate = 1
                    AND (SELECT count(1) AS num FROM member m WHERE m.user_id = u.id) = 0;

作者 admin

百度广告效果展示