要求所有的众多符合标准筛选一个一对多查询
-
20-08-2019 - |
题
想象以下表:
创建表盒(ID INT,名称文本,...);
创建表thingsinboxes(ID INT,box_id INT,事枚举( '苹果' 香蕉”, '桔子');
和的表如下所示:
Boxes: id | name 1 | orangesOnly 2 | orangesOnly2 3 | orangesBananas 4 | misc thingsinboxes: id | box_id | thing 1 | 1 | orange 2 | 1 | orange 3 | 2 | orange 4 | 3 | orange 5 | 3 | banana 6 | 4 | orange 7 | 4 | apple 8 | 4 | banana
我如何选择包含至少一个橙色并没有什么箱子,是不是橘子?
请问这个规模,假设我有几十万箱,并可能上百万的东西在盒子里?
我想保持这一切在SQL如果可能的话,而不是处理后的结果与脚本设置。
我使用两者的Postgres和MySQL,所以子查询可能是坏的,给定的MySQL不优化子查询(预版本6,反正)。
解决方案
SELECT b.*
FROM boxes b JOIN thingsinboxes t ON (b.id = t.box_id)
GROUP BY b.id
HAVING COUNT(DISTINCT t.thing) = 1 AND SUM(t.thing = 'orange') > 0;
下面是一种不使用GROUP BY另一种解决方案:
SELECT DISTINCT b.*
FROM boxes b
JOIN thingsinboxes t1
ON (b.id = t1.box_id AND t1.thing = 'orange')
LEFT OUTER JOIN thingsinboxes t2
ON (b.id = t2.box_id AND t2.thing != 'orange')
WHERE t2.box_id IS NULL;
与往常一样,你做出一个查询的可扩展性和性能的结论之前,请你必须与现实的数据集尝试,并测量性能。
其他提示
我觉得比尔Karwin的查询是蛮好的,但是如果一个框的比例相对较小含有橙子,你应该能够通过在thing
领域使用索引来加快速度:
SELECT b.*
FROM boxes b JOIN thingsinboxes t1 ON (b.id = t1.box_id)
WHERE t1.thing = 'orange'
AND NOT EXISTS (
SELECT 1
FROM thingsinboxes t2
WHERE t2.box_id = b.id
AND t2.thing <> 'orange'
)
GROUP BY t1.box_id
在WHERE NOT EXISTS
子查询只会每橙色的东西运行一次,所以它不是太昂贵提供不会有太多的橘子。
不隶属于 StackOverflow