从2个MySQL表中选择非重复记录

时间:2015-02-20 01:12:49

标签: php mysql sql duplicate-removal

我有2张表: 1.下载的门票 2.兑换票据

每个表都有属性" ticketid"。

我想找到下载机票但没有兑换机票的人 - 基本上是找不到重复(独特)的票据。

我的查询(PHP)如下:

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

我没有得到任何输出。

4 个答案:

答案 0 :(得分:2)

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

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

LEFT JOIN操作为每个下载的故障单及其兑换创建结果行。如果没有兑换,则redeemed.ticketid为NULL,因此此查询使用WHERE来仅选择那些项目。

答案 1 :(得分:1)

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

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

答案 2 :(得分: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;

答案 3 :(得分:1)

您的查询似乎应该返回指定的结果。您获得的结果(没有行)的一个可能的解释是没有任何未兑换的下载票据。

这个查询似乎假设ticketid表中的downloadedtickets是UNIQUE,而redeemedtickets表中的UNIQUE ......可能是这种情况,但我们没有我们提供的规范中的信息。 (如果不是这种情况,那么来自ticketid表的downloadedtickets的COUNT(*)可能大于1。

ticketid是否用于“匹配”两个表中的行的右列?我们假设它是,因为这是您的查询使用的。 (如果不是,那也可以解释你得到的结果。)

您的查询形式(更容易阅读):

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

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

对于大型集,实现内联视图可能会很昂贵。

就个人而言,我更喜欢使用更有效的“反连接”模式的查询:

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

这基本上说,返回downloadedtickets的所有行,以及来自redeemed票证的任何“匹配”行。 LEFT关键字使其成为“外部”连接,因此我们从左侧的表中获取所有行,无论右侧表中是否存在匹配的行。诀窍是WHERE子句中的谓词,它过滤掉所有匹配的行。 (如果匹配,我们保证来自ticketid的{​​{1}}将为非NULL。因此,该表中唯一具有NULL值的行将是来自{{1}的行那没有匹配。

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

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