Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 选择具有满足某些约束的多个子关系的所有行_Sql_Postgresql - Fatal编程技术网

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'
    
  • 权重约束只是“每个子关系必须满足某些约束”的占位符。在实践中,我们需要通过日期范围、状态等来限制子关系,但我不想使示例进一步复杂化

    (我正在使用postgresql,以防解决方案需要特定于数据库。)

    这是你期望的吗


    这是您所期望的吗?

    我强烈建议使用
    分组方式和
    拥有

    对于第一个问题,此查询应适用于:

    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%的解决方案(根据查询分析器)。