mysql - 给定两个具有公共(public)字段 F 的表 A 和 B,我如何有效地找到 A 中不存在于 B 中的所有 F?

标签 mysql sql

我有一个投票系统,我正在尝试为 MySQL 编写一个查询,以检测哪些投票已完成,以便可以将电子邮件发送给投票的创建者。当 (1) 他们的时间用完(已经很容易地解决了那个问题)或 (2) 当所有选民都投票时,投票就完成了。

有两个表与此相关。第一个表是“votes”,其中描述了每个投票并具有唯一的“vote_id”。第二张表是“门票”。在创建投票时,每个参与者都创建了一张票(其中包含一些身份验证信息)。每张票都有一个“vote_id”字段,对应于“votes”表中的字段。所以基本上,当人们投票时,他们相应的票从票表中删除。这意味着给定“vote_id”的“票”中的行数对应于未投票的人数。

一开始我是这样去做的:

SELECT votes.vote_id
FROM votes, tickets
WHERE votes.vote_id=tickets.vote_id
AND (votes.completion_timestamp < NOW())
HAVING (COUNT(tickets.vote_id) = 0)

但后来我意识到......因为“votes.vote_id=tickets.vote_id”行......我想这意味着没有未决票的选票将被忽略。我可以想到很多低效的方法来做到这一点,但我想在 MySQL 中有一种方法可以做到这一点吗?

问题的概括性总结:给定两个表 A 和 B,它们有一个公共(public)字段 F,我如何找到 A 中不存在于 B 中的所有 F?

最佳答案

要在 MySQL 中高效做到这一点需要一个技巧:

select v.*
from votes v
where votes.completion_timestamp < NOW() and
      not exists (select 1 from tickets t where t.vote_id = v.vote_id)

您的 SQL 不太正确。以下版本应该可以工作:

SELECT distinct votes.vote_id
FROM votes left outer join
     tickets
     on votes.vote_id=tickets.vote_id
where votes.completion_timestamp < NOW()) and
      tickets.vote_id is null 

在 MySQL 文档 (http://dev.mysql.com/doc/refman/5.0/en/subquery-optimization-with-exists.html) 中广泛讨论了 EXISTS 与 IN 与子查询的使用。与左外部连接的区别在于两点。加入策略并增加 I/O。

我不知道左外连接的 JOIN 策略是否不同。我推测它应该不会比 EXISTS 版本差。不过,第二点是左外部联接创建的输出集可能会增加行数。 EXISTS 版本无法做到这一点。

阅读文档后,以下内容可能会更有效:

select v.*
from votes v
where votes.completion_timestamp < NOW() and
      not exists (select 1 from tickets t where t.vote_id = v.vote_id limit 1)

限制应该使遇到的第一行以外的任何评估短路。

关于mysql - 给定两个具有公共(public)字段 F 的表 A 和 B,我如何有效地找到 A 中不存在于 B 中的所有 F?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12076323/

相关文章:

C# Linq 连接表,其中左表可能为空

php - cakephp 从 5.4 迁移到 5.3 时出现 mysql 编码问题

mysql - Latin 与 utf8 字符集和索引使用(mysql 5.5)

java - mysql jdbc 通信异常

php - 回显来自 mysql_query 的所有结果

sql - 在sql server中计算每天的平均值

sql - SQL 的括号表示法在 Microsoft Access 中不起作用

mysql - 基于第一次出现的sql动态限制

java - 即使通过 MimetypesFileTypeMap 设置内容类型后,如果下载的文件具有除 pdf 之外的任何其他扩展名,也将无法打开

php - 在预定义的时间运行自动查询