我有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";
我没有得到任何输出。
答案 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 EXISTS
,NOT IN
或LEFT 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
。
这不是唯一会返回指定结果的查询,还有其他查询模式可以返回等效结果。