セット内の2つの列の場所を選択する


35

これはばかげた質問かもしれません。私の疑いはこれができないということですが、SQLには次のようなことができる構造があります。

SELECT whatever WHERE col1,col2 IN ((val1, val2), (val1, val2), ...)

2つの列がペアになっているデータを選択したい。

可能であれば、サブクエリの使用を避けたいです。

回答:


49

次のようなことをできるSQLの構成体はありますか?

はい、あなたが書いたのとほぼ同じです。col1, col2括弧の中に入れるだけです:

-- works in PostgreSQL, Oracle, MySQL, DB2, HSQLDB 
SELECT whatever 
FROM t                               --- you missed the FROM
WHERE (col1, col2)                    --- parentheses here
       IN ((val1a, val2a), (val1b, val2b), ...) ;

ただし、DBMSで試してみると、機能しないことがあります。すべてのDBMSが(進化する)SQL標準のすべての機能を実装しているわけではないためです。これは、Oracle、MySQL、Postgres、DB2、およびHSQLDBの最新バージョンで機能します(MySQLで最適化されておらず、インデックスを使用しないため、5.7で修正しない限り、回避する必要があります)。

IN演算子についてはMySQLのドキュメントを、行コンストラクタについてはPostgresのドキュメントを参照してください。括弧内の2つ(またはそれ以上)の値は、行コンストラクターと呼ばます。

同じ考えを表現する他の方法:

-- works in PostgreSQL, DB2
SELECT whatever 
FROM t 
WHERE (col1, col2) 
       IN ( VALUES (val1a, val2a), (val1b, val2b), ...) ;

SELECT t.whatever 
FROM t 
  JOIN 
    ( VALUES (val1a, val2a), (val1b, val2b), ...) AS x (col1, col2)
      ON (x.col1, x.col2) = (t.col1, t.col2) ;

どちらもPostgresとDB2(afaik)で動作します。最後のものもSQL Serverで動作するように変更できます。

-- works in PostgreSQL, DB2, SQL Server
SELECT t.whatever 
FROM t 
  JOIN 
    ( VALUES (val1a, val2a), (val1b, val2b), ...) AS x (col1, col2)
      ON  x.col1 = t.col1
      AND x.col2 = t.col2 ;

また、最初に値を(一時または永続)テーブルに配置することで、どこでも機能するように変更することもできます。

-- works everywhere
CREATE TABLE values_x
( col1  ...,
  col2  ...) ;

-- use appropriate for the DBMS syntax here
INSERT INTO values_x (col1, col2)
VALUES (val1a, val2a), (val1b, val2b), ... ;

SELECT t.whatever 
FROM t 
  JOIN values_x  x 
      ON  x.col1 = t.col1
      AND x.col2 = t.col2 ;

DROP TABLE values_x ;

そして、常に長い道のりINがあり、それを長い表現に変換するORことはどこでも機能するはずです:

-- works in all SQL DBMS
SELECT whatever 
FROM t  
WHERE col1 = val1a AND col2 = val2a
   OR col1 = val1b AND col2 = val2b
   ---
   ;

*:実際にはROW(v)、Postgresのドキュメントを参照して、1つの値のみにすることができます。


に関するドキュメントはどこにありますWHERE (x, y) IN (a,b)か?MySqlを使用しています。おそらく、このコンストラクトの名前がわからないでしょう。
ロバートロシャ

1
@RobertRochaが追加したリンクを参照してください。それは行コンストラクタと呼ばれますINMySQL:およびPostgres:行コンストラクタ
ypercubec

もありWHERE EXISTS (SELECT t.col1, t.col2 [FROM DUAL] INTERSECT VALUES(val1, val2), (…, …), …)ます。
アンドリーM

-4
SELECT * 
FROM   dbo.Table1 A
WHERE  (CAST(Column1 AS VARCHAR(max)) + '-' + CAST(Column2 AS varchar(max)))
NOT IN (SELECT (CAST(Column1 AS VARCHAR(max)) 
                + '-' 
                + CAST(Column2 AS varchar(max))) 
        FROM Table2)

2
それは確実に動作しません
-a_horse_with_no_name

2
はい。非効率性のほかに、区別することはできません'a-b', 'c''a', 'b-c'。そして、に変換できない型に対しては惨めに失敗しvarchar(max)ます。
ypercubeᵀᴹ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.