it-swarm-eu.dev

výběr umístění dvou sloupců v sadě

Může to být hloupá otázka a mám podezření, že to nemohu udělat, ale existuje v SQL konstrukt, který by mi umožnil dělat něco jako následující:

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

Chci vybrat data, kde jsou dva sloupce v sadě párů.

Chtěl bych se vyhnout použití subdodávky, pokud je to možné.

38
James

Existuje v SQL konstrukt, který by mi umožnil dělat něco jako následující:

Ano, existuje téměř přesně tak, jak jste to napsali. Stačí do závorek vložit 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), ...) ;

Pokud to zkusíte v DBMS, možná zjistíte, že to nefunguje. Protože ne všechny DBMS implementovaly všechny funkce (vyvíjejícího se) standardu SQL. Funguje to v nejnovějších verzích Oracle, MySQL, Postgres, DB2 a HSQLDB (nebylo to v MySQL dobře optimalizováno a nepoužívaly indexy, proto by se tam nemělo vyhýbat, pokud to neřeší v 5.7).

Viz MySQL dokumentace o IN operator a Postgres dokumentace o Row konstruktory . Dvě * (nebo více) hodnot v závorkách se nazývají konstruktory řádků .

Další způsoby, které vyjadřují stejnou myšlenku:

-- 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) ;

Oba pracují v Postgresu a DB2 (afaik). Poslední může být také upraven tak, aby fungoval na serveru 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 ;

Může být také upraven tak, aby fungoval všude, nejprve uložením hodnot do (dočasné nebo trvalé) tabulky:

-- 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 ;

A vždy existuje dlouhá cesta nebo převod IN na dlouhý výraz s OR, který by měl fungovat všude:

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

*: Ve skutečnosti to může být jen jedna hodnota, s ROW(v), viz Postgres docs.

51
ypercubeᵀᴹ