chọn hai cột trong một tập hợp


35

Đây có thể là một câu hỏi ngớ ngẩn và sự nghi ngờ của tôi là tôi không thể làm điều này, nhưng có một cấu trúc nào trong SQL cho phép tôi làm điều gì đó như sau:

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

Tôi muốn chọn dữ liệu trong đó hai cột nằm trong một cặp các cặp.

Tôi muốn tránh sử dụng truy vấn con, nếu có thể.

Câu trả lời:


48

Có một cấu trúc trong SQL sẽ cho phép tôi làm một cái gì đó như sau:

Vâng, có, gần như chính xác như bạn đã viết nó. Chỉ cần đặt col1, col2trong ngoặc đơn:

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

Tuy nhiên, nếu bạn thử nó trong DBMS, bạn có thể thấy rằng nó không hoạt động. Bởi vì không phải tất cả DBMS đã triển khai tất cả các tính năng của tiêu chuẩn SQL (đang phát triển). Điều này hoạt động trong các phiên bản mới nhất của Oracle, MySQL, Postgres, DB2 và HSQLDB (nó không được tối ưu hóa tốt trong MySQL và không sử dụng các chỉ mục, vì vậy nên tránh ở đó trừ khi họ sửa nó trong 5.7).

Xem tài liệu MySQL về INtoán tử và tài liệu Postgres về hàm tạo Row . Hai giá trị * (hoặc nhiều hơn) trong ngoặc đơn được gọi là hàm tạo hàng .

Những cách khác thể hiện cùng một ý tưởng:

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

Cả hai đều hoạt động trong Postgres và DB2 (afaik). Cái cuối cùng cũng có thể được sửa đổi để hoạt động trong 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 ;

Nó cũng có thể được sửa đổi để hoạt động ở mọi nơi, bằng cách đặt các giá trị vào bảng (tạm thời hoặc vĩnh viễn) trước:

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

Và luôn luôn có một chặng đường dài hoặc chuyển đổi INmột biểu thức dài với ORđiều đó sẽ hoạt động ở mọi nơi:

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

*: Nó thực sự có thể chỉ là một giá trị, với ROW(v), xem tài liệu Postgres.


Tôi có thể tìm tài liệu về WHERE (x, y) IN (a,b)đâu? Tôi đang sử dụng MySql. Có lẽ tôi không biết cấu trúc này được gọi là gì.
Robert Rocha

1
@RobertRocha xem các liên kết tôi đã thêm. Nó được gọi là hàm tạo hàng: MySQL:INPostgres: Row
Con constructor

Cũng có WHERE EXISTS (SELECT t.col1, t.col2 [FROM DUAL] INTERSECT VALUES(val1, val2), (…, …), …).
Andriy 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
Điều đó sẽ không hoạt động đáng tin cậy
a_horse_with_no_name

2
Vâng. Bên cạnh sự không hiệu quả, nó sẽ không thể phân biệt giữa 'a-b', 'c''a', 'b-c'. Và nó sẽ thất bại thảm hại cho bất kỳ loại nào không thể chuyển đổi thành varchar(max).
ypercubeᵀᴹ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.