【问题标题】:SQL: Select records where ALL joined records satisfy some conditionSQL:选择所有连接记录都满足某些条件的记录
【发布时间】:2010-07-27 04:46:59
【问题描述】:

如何编写一个 SQL 查询,仅当连接表中的所有关联记录都满足某个条件时才返回记录。

例如,如果 A 有很多 B,我想 SELECT * FROM A WHERE 给定 A 的所有相关 B 都有 B.some_val > 值

我知道这可能是一个非常基本的问题,因此感谢您的帮助。另外,如果它有所作为,我正在使用 postgres。

山姆

【问题讨论】:

    标签: sql postgresql join


    【解决方案1】:

    假设不需要关联,使用:

    SELECT a.*
      FROM A a
     WHERE EXISTS(SELECT NULL
                    FROM B b
                  HAVING MIN(b.some_val) > a.val)
    

    如果您确实需要相关性:

    SELECT a.*
      FROM A a
     WHERE EXISTS(SELECT NULL
                    FROM B b
                   WHERE b.id = a.id
                  HAVING MIN(b.some_val) > a.val)
    

    说明

    EXISTS 基于第一个匹配对布尔值进行评估 - 这比使用 IN 更快,并且 - 与使用 JOIN 不同 - 不会重复行。 SELECT 部分无关紧要 - 您可以将其更改为 EXISTS SELECT 1/0 ...,尽管存在明显的除零错误,但查询仍然可以工作。

    EXISTS 中的子查询使用聚合函数 MIN 来获取最小的 B.some_val - 如果该值大于 a.val 值,则 a.val 小于所有 b 值。 WHERE 子句的唯一需要是用于关联 - 聚合函数只能在 HAVING 子句中使用。

    【讨论】:

    • 刚刚测试过,应该不需要 GROUP BY。很好的解决方案(尽管 op 说“所有相关的 B”,这意味着存在的 b.some_id = a.some_id 可能存在 WHERE 子句)。
    • 这也可能是最通用的答案,因为 HAVING 子句可以很容易地扩展。 IE。 HAVING a.val = ALL(array_agg(b.some_val)) 等。
    • @OMG:你能解释一下你的答案是怎么回事吗?使用 EXISTS 来表示“所有人”让我大吃一惊。
    • @Justin K:第 1 部分 - EXISTS 根据第一个匹配对布尔值进行评估 - 这比使用 IN 更快,并且 - 与使用 JOIN 不同 - 不会重复行. SELECT 部分无关紧要 - 您可以将其更改为 EXISTS SELECT 1/0 ...,尽管存在明显的除零错误,但查询仍然有效。
    • @Justin K:第 2 部分:EXISTS 中的子查询使用聚合函数 MIN 来获得最小的 B.some_val - 如果该值大于 a.val 值,则 a.val 为小于所有 b 值。 WHERE 子句的唯一需要是关联 - 聚合函数只能在 HAVING 子句中使用。
    【解决方案2】:
    select * from A
     where -- at least one record in B is greater than some_val
           exists (select null from B
                    where B.some_val > :value
                      and A.join_column = B.join_column)
       and -- no records in B are not greater than some_val
           not exists (select null from B
                        where B.some_val <= :value
                          and A.join_column = B.join_column)
    

    【讨论】:

      【解决方案3】:

      以下应该有效:

      SELECT *
      FROM a
      JOIN b ON a.key = b.key AND a.value > b.value
      

      因为这是一个 inner join 而不是 outer join,所以来自 A 的记录只有在 B 中有满足条件的记录时才会被包括在内。

      我不使用 PostGRE,所以我不能保证语法完全正确。

      【讨论】:

        【解决方案4】:

        你想要一个 INNER JOIN:

        SELECT
            A.*
        FROM
            A
        INNER JOIN B
            ON A.identifier = B.identifier
        WHERE
            B.some_val > value
        

        您需要确保存在从 A 到 B 的外键,或其他一些通用标识符。

        【讨论】:

          【解决方案5】:
          select * from a where a.key = b.a_key where b.value > condition
          

          【讨论】:

            【解决方案6】:

            以书店和书籍为例。

            书店

            书店ID, bookID

            bookID、价格

            我想你想退回所有书的价格都大于 X 的书店。

            select *
            from Bookstore bs1
            where bs1.bookstoreID not exist
             (
              select bs.bookstoreID
              from Bookstore bs, Book b
              where bs.bookID= b.bookID
              b.price < x;   -- your value                                                     
             )
            

            【讨论】:

              猜你喜欢
              • 2017-07-15
              • 1970-01-01
              • 1970-01-01
              • 2020-09-03
              • 2022-01-23
              • 1970-01-01
              • 2019-07-30
              • 2019-04-29
              • 2017-11-26
              相关资源
              最近更新 更多