Sql 选择具有满足某些约束的多个子关系的所有行
比如说,我有一个篮子清单,里面可以装一定重量的水果:Sql 选择具有满足某些约束的多个子关系的所有行,sql,postgresql,Sql,Postgresql,比如说,我有一个篮子清单,里面可以装一定重量的水果: Table baskets (id, name) ---------------- 1, 'apples, oranges and more' 2, 'apples and small oranges' 3, 'apples and bananas' 4, 'only oranges' 5, 'empty' Table basket_fruits (id, basket, fruit, weight) ---------------- 1,
Table baskets
(id, name)
----------------
1, 'apples, oranges and more'
2, 'apples and small oranges'
3, 'apples and bananas'
4, 'only oranges'
5, 'empty'
Table basket_fruits
(id, basket, fruit, weight)
----------------
1, 1, 'apple', 2
2, 1, 'apple', 3
3, 1, 'orange', 2
4, 1, 'banana', 2
5, 2, 'apple', 2
6, 2, 'orange', 1
7, 3, 'apple', 2
8, 3, 'banana', 2
9, 4, 'orange', 2
我正在努力为这两种情况提出合理有效的查询:
苹果
和至少一个橙色
,每个篮子的重量都超过给定的重量。因此,权重>=2
的预期结果为
1, 'apples, oranges and more'
对于重量>=1
,它是
1, 'apples, oranges and more'
2, 'apples and small oranges'
weight>=2
我希望
5, 'empty'
对于weight>=3
,它应该返回
2, 'apples and small oranges'
3, 'apples and bananas'
4, 'only oranges'
5, 'empty'
这是您所期望的吗?我强烈建议使用
分组方式和拥有
对于第一个问题,此查询应适用于:
SELECT b.name
FROM baskets b INNER JOIN
basket_fruits bf
ON b.id = bf.basket
GROUP BY b.name
HAVING SUM( (bf.fruit = 'apple' AND bf.weight >= 2)::int ) > 0 AND
SUM( (bf.fruit = 'orange' AND bf.weight >= 2)::int ) > 0 ;
第二个比较复杂,因为没有行。但是左连接
和合并()
就足够了,因此您可以用相同的格式来表达它:
SELECT b.name
FROM baskets b LEFT JOIN
basket_fruits bf
ON b.id = bf.basket
GROUP BY b.name
HAVING SUM( (COALESCE(bf.weight, 0) >= 2)::int ) = 0
为此,我强烈建议使用groupby
和have
对于第一个问题,此查询应适用于:
SELECT b.name
FROM baskets b INNER JOIN
basket_fruits bf
ON b.id = bf.basket
GROUP BY b.name
HAVING SUM( (bf.fruit = 'apple' AND bf.weight >= 2)::int ) > 0 AND
SUM( (bf.fruit = 'orange' AND bf.weight >= 2)::int ) > 0 ;
第二个比较复杂,因为没有行。但是左连接
和合并()
就足够了,因此您可以用相同的格式来表达它:
SELECT b.name
FROM baskets b LEFT JOIN
basket_fruits bf
ON b.id = bf.basket
GROUP BY b.name
HAVING SUM( (COALESCE(bf.weight, 0) >= 2)::int ) = 0
以下是我目前的解决方案:
所有装有两种水果且重量>=2
的篮子(感谢Gordon Linoff的建议):
所有不带水果且重量>=2的篮子:
SELECT b.* FROM baskets b
LEFT JOIN (
SELECT basket, fruit FROM basket_fruits
WHERE weight >= 2
) bf ON b.id = bf.basket
WHERE fruit IS NULL
如果有人有更有效的想法,我很乐意听听。以下是我目前的解决方案:
所有装有两种水果且重量>=2
的篮子(感谢Gordon Linoff的建议):
所有不带水果且重量>=2的篮子:
SELECT b.* FROM baskets b
LEFT JOIN (
SELECT basket, fruit FROM basket_fruits
WHERE weight >= 2
) bf ON b.id = bf.basket
WHERE fruit IS NULL
如果有人有更有效的想法,我很乐意听到。谢谢,但这是假设对空篮子的了解,不会产生任何特定的结果。谢谢,但这是假设对空篮子的了解,不会产生任何特定的结果。“高于给定的权重”…这是每个水果的重量,还是篮子的总重量?不清楚。@ADyson,每个都必须高于重量。我已经相应地重新表述了这个问题,并为这个限制添加了一个解释。“超过给定的重量”……这是每个水果的重量,还是篮子的总重量?不清楚。@ADyson,每个都必须高于重量。我已经相应地重新制定了问题,并为约束添加了解释。谢谢你的建议!您的解决方案非常昂贵且速度缓慢,与我的要求不符,无法获取完整的篮行。但是你的“SUM(fruit=…)”想法真的很有价值,帮助我找到了一个成本只有10-20%的解决方案(根据查询分析器)。谢谢你的建议!您的解决方案非常昂贵且速度缓慢,与我的要求不符,无法获取完整的篮行。但是你的“SUM(fruit=…)”想法非常有价值,它帮助我找到了一个成本只有10-20%的解决方案(根据查询分析器)。