【问题标题】:Select Query by Pair of fields using an in clause使用 in 子句按字段对选择查询
【发布时间】:2012-05-30 08:28:23
【问题描述】:

我有一张名为 player 的桌子,如下所示:

First_Id    Second_Id     Name
1           1             Durant
2           1             Kobe
1           2             Lebron
2           2             Dwight
1           3             Dirk

我希望在这个表上写一个 select 语句来检索第一个 id 和第二个 id 与一组指定的第一个和第二个 id 匹配的所有行。

例如,我希望选择第一个和第二个 id 如下的所有行:(1,1)、(1,2) 和 (1,3)。这将检索以下 3 行:

First_Id    Second_Id    Name
1           1            Durant
1           2            Lebron
1           3            Dirk

是否可以用如下方式编写选择查询:

SELECT * 
FROM PLAYERS
WHERE (First_Id, Second_Id) IN ((1,1), (1,2) and (1,3))?

如果有办法编写类似于上面的SQL我想知道。有没有办法为表示多行的 IN 子句指定值,如图所示。

我正在使用 DB2。

【问题讨论】:

    标签: sql database db2 in-clause


    【解决方案1】:

    这适用于我的 DB2(Linux/Unix/Windows 上的 9.7 版),使用以下语法:

    SELECT *
    FROM PLAYERS
    WHERE (First_Id, Second_Id) IN (VALUES (1,1), (1,2), (1,3))
    

    此语法不适用于 Mainframe 上的 DB2(至少在 9.1 版中),因为您不能用 VALUES 表达式替换子选择。此语法将起作用:

    SELECT *
    FROM PLAYERS
    WHERE (First_Id, Second_Id) IN (SELECT 1, 1 FROM SYSIBM.SYSDUMMY1 UNION ALL
                                    SELECT 1, 2 FROM SYSIBM.SYSDUMMY1 UNION ALL
                                    SELECT 1, 3 FROM SYSIBM.SYSDUMMY1)
    

    【讨论】:

    • 这不是标准 SQL,但它提供了特定于数据库的解决方案。
    • @GordonLinoff 我同意,但他确实说他正在使用 DB2。 :)
    • 第一种语法 (WHERE (f, s) IN (VALUES (1,1), (1,2))) 也适用于 PostgreSQL,并且在文档中说它是一种标准 SQL:postgresql.org/docs/current/static/sql-values.html
    【解决方案2】:

    这是 postgresql 中一个非常相似的解决方案:

    SELECT tmp_table.val1, tmp_table.val2
    FROM tmp_table
    WHERE (tmp_table.val1, tmp_table.val2) not in (select tmp_table2.val1, tmp_table2.val2 from tmp_table2);
    

    【讨论】:

    • 注意:这并不是所要求的,我使用以前的 cmets 来解决我将临时表中的两个值 val1、val2 插入到实际表中的具体问题,而这个实际表在 (val1, val2) 上有一个唯一键。在插入之前,我必须找到一种方法来删除 tmp_table 中的那些密钥对。这是我插入的子句的选择部分。
    【解决方案3】:

    使用复合主键,我将连接两个 id 并匹配复合字符串。

    select id1 + id2 as FullKey, *
    from players
    where FullKey in ('11','12','13')
    

    (如果 id 不是字符串,只需将它们转换为字符串。)

    【讨论】:

    • 虽然连接键列是一种有用的方法,但在列之间包含分隔符会更安全。虽然在本例中 ORDER BY 子句可以引用列别名,例如 FullKey,但 DB2 只允许表别名,而 WHERE 子句中不允许列别名。
    • 我明白了。没有意识到 DB2 对列别名有这样的限制。不过,在 WHERE 中使用复合 id1 + id2(或 id1 + delim + id2,你说得对,这是一个更好的主意)应该可以解决问题。
    • 您需要添加一个分隔符,您必须确保它不在结果中。 ('ab', 'cd')('abc', 'd') 之类的重复项总是有可能连接到 abcd
    【解决方案4】:
    SELECT * FROM <your table> where (<field1>, <field2>, ...) in (SELECT <field1>, <field2>, ... FROM <your table> where <your condition>)
    

    这对我来说很神奇。

    【讨论】:

    • 谢谢!它在 TimescaleDB 2.0 中对我有用,并且 EXPLAIN ANALYZE 显示了一些性能改进。
    【解决方案5】:

    此语法适用于 MySQL:

    SELECT *
    FROM PLAYERS
    WHERE (First_Id, Second_Id) IN ((1,1), (1,2), (1,3))
    

    【讨论】:

      【解决方案6】:

      这种类型的查询适用于 DB2。

      SELECT * FROM A
      WHERE (C1, C2) IN (SELECT B1, B2 FROM B WHERE B3=1);
      

      【讨论】:

        猜你喜欢
        • 2011-09-11
        • 2019-09-05
        • 2018-11-21
        • 1970-01-01
        • 2018-01-05
        • 2011-04-18
        • 2013-07-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多