Select 个来自 2 MySQL 个表的非重复记录

Select non-duplicated records from 2 MySQL tables

我有 2 个 table,即: 1.下载门票 2. 兑换门票

每个 table 都有属性 "ticketid"。

我想找到下载票但没有兑换票的人 - 本质上,找到非重复(唯一)的票证。

我的查询(PHP)如下:

$sql = "
SELECT ticketid 
FROM (
  SELECT ticketid 
  FROM downloadedtickets 
  UNION ALL 
  SELECT ticketid 
  FROM redeemedtickets
)
GROUP BY ticketid 
HAVING COUNT(*) = 1";

我没有从中得到任何输出。

执行此操作的一个好方法是左连接,并测试 NULL。

SELECT d.ticketid
  FROM downloadedtickets d 
  LEFT JOIN redeemedtickets r USING(ticketid)
 WHERE r.ticketid IS NULL

LEFT JOIN 操作为每张下载的门票及其兑换创建一个结果行。在没有兑换的地方,redeemed.ticketid 为 NULL,因此此查询仅使用 WHERE 来 select 那些项目。

您应该指定并汇总您正在统计的字段。见下文:

$sql = "SELECT COUNT(ticketid)ticketid FROM downloadedtickets UNION ALL SELECT ticketid FROM redeemedtickets GROUP BY ticketid HAVING COUNT(ticketid) = 1";

我会使用 NOT EXISTSNOT INLEFT JOIN 来解决这个问题。这是后一个版本:

select d.*
from downloadedtickets d left outer join
     redeemedtickets r
     on d.ticketid = r.ticketid
where r.ticketid is null;

您的查询似乎应该 return 指定的结果。对于您得到的结果(无行)的一种可能解释是没有任何未兑换的已下载门票。

此查询似乎假定 ticketiddownloadedtickets table 中是唯一的,并且在 redeemedtickets table 中是唯一的...是这样,但我们没有从我们提供的规范中获得该信息。 (如果不是这种情况,那么仅来自 downloadedtickets table 的 ticketid 的 COUNT(*) 可能大于一个。

ticketid 是用于 "match" 来自两个 table 的行的正确列吗?我们假设它是,因为这就是您的查询所使用的。 (如果不是,那也可以解释您得到的结果。)

您的查询采用以下形式(更容易阅读):

SELECT t.ticketid 
  FROM ( SELECT d.ticketid
           FROM downloadedtickets d
          UNION ALL
         SELECT r.ticketid
           FROM redeemedtickets r
       ) t
 GROUP BY t.ticketid
HAVING COUNT(*) = 1

我们注意到,对于 redeemedtickets 中不在 downloadedtickets 中的行,此查询有可能 return ticketid。可能有某种保证不会发生这种情况,但同样,规范中没有该信息。

对于大型集合,实现内联视图的成本可能很高。

就个人而言,我更喜欢使用具有更高效 "anti-join" 模式的查询:

SELECT d.ticketid
  FROM downloadedtickets d
  LEFT
  JOIN redeemedtickets r 
    ON r.ticketid = d.ticketid
 WHERE r.ticketid IS NULL
 ORDER BY d.ticketid

这实际上是说,return 来自 downloadedtickets 的所有行,以及来自 redeemed 票的任何 "matching" 行。 LEFT 关键字使它成为一个 "outer" 连接,因此我们从左侧的 table 中获取所有行,无论左侧的 table 中是否存在匹配的行右边。诀窍是 WHERE 子句中的谓词,它过滤掉所有匹配的行。 (如果匹配,我们保证 redeemedtickets 中的 ticketid 将是非 NULL。因此,table 中唯一具有 NULL 值的行将是来自downloadedtickets 没有匹配项。

此查询可以有效利用 redeemedtickets 上的索引,其前导列为 ticketid

这不是唯一会 return 指定结果的查询,还有其他查询模式可以 return 等效结果。