想象以下表:

创建表盒(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子查询只会每橙色的东西运行一次,所以它不是太昂贵提供不会有太多的橘子。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top