我正在阅读 Bill Karwin 的《 SQL Antipattern》 一书。在第18章中,他讨论了有关此示例的错误的复杂查询:
SELECT p.product_id,
COUNT(f.bug_id) AS count_fixed,
COUNT(o.bug_id) as count_open
FROM BugsProducts p
LEFT Outer JOIN (BugsProducts bpf JOIN Bugs f Using (bug_id))
ON (p.bug_id = f.bug_id AND f.status = 'FIXED')
LEFT OUTER JOIN (BugsProducts bpo JOIN Bugs o Using (bug_id))
ON (p.bug_id = o.bug_id AND o.status = 'OPEN')
WHERE p.product_id = 1
GROUP BY p.product_id
他声称:
您碰巧知道实际上有11个固定的错误, 给定产品的七个未解决的错误。所以查询的结果是 令人费解:
product_id | count_fixed | count_open 1 | 77 | 77
然后解释说,发生这种情况是因为结果是固定和开放错误之间的笛卡尔积。
我不明白为什么会发生这种情况,因此我使用MySQL 5.7.25重建了此查询。
结果令人惊讶
product_id | count_fixed | count_open
1 | 11 | 7
也可以简单地将(BugsProducts bpf JOIN Bugs f Using (bug_id))
替换为Bugs f
,将(BugsProducts bpf JOIN Bugs o Using (bug_id))
替换为Bugs o
。
为什么声称该查询应做笛卡尔乘积?由于MySQL的某些特殊性在其他数据库中不起作用,因此查询是否仅返回11/7结果?
答案 0 :(得分:1)
两个左联接有时会产生笛卡尔积。
在这种情况下,查询根本没有意义。很有可能是一个错误。
尝试删除GROUP BY p.product_id
并将select子句更改为:
SELECT p.product_id,
f.bug_id AS bug1Id,
o.bug_id as bug2Id
这样,结果集将更加明显。
我假设我们有以下表格:
其中BugsProducts是Products和Bug之间的联接表
对于查询,它正在尝试
无论如何,我相信作者想证明的东西是这样的:
SELECT p.product_id,
COUNT(f.bug_id) AS count_fixed,
COUNT(o.bug_id) as count_open
FROM Products p
LEFT Outer JOIN (BugsProducts bpf JOIN Bugs f Using (bug_id))
ON (bpf.product_id = p.product_id AND f.status = 'FIXED')
LEFT OUTER JOIN (BugsProducts bpo JOIN Bugs o Using (bug_id))
ON (bpo.product_id = p.product_id AND o.status = 'OPEN')
WHERE p.product_id = 1
Group by p.product_id
产生笛卡尔积。