Tốt hơn nên bao gồm mã câu hỏi của bạn, thay vì dữ liệu văn bản mơ hồ, để chúng tôi đều làm việc với cùng một dữ liệu. Dưới đây là lược đồ mẫu và dữ liệu tôi đã giả định:
CREATE TABLE tbl_data (
id INT NOT NULL,
code_1 CHAR(2),
code_2 CHAR(2)
);
INSERT INTO tbl_data (
id,
code_1,
code_2
)
VALUES
(1, 'AB', 'BC'),
(2, 'BC', NULL),
(3, 'DE', 'EF'),
(4, NULL, 'BC');
Như Blorgbeard nhận xét, các DISTINCT
điều khoản trong giải pháp của bạn là không cần thiết vì các nhà điều hành UNION
loại bỏ các hàng trùng lặp. Có một toán tử UNION ALL
không loại bỏ trùng lặp, nhưng nó không thích hợp ở đây.
Viết lại câu hỏi của bạn mà không cần mệnh đề DISTINCT
là một giải pháp tốt cho vấn đề này:
SELECT code_1
FROM tbl_data
WHERE code_1 IS NOT NULL
UNION
SELECT code_2
FROM tbl_data
WHERE code_2 IS NOT NULL;
Nó không quan trọng mà hai cột là trong cùng một bảng. Giải pháp sẽ giống nhau ngay cả khi các cột nằm trong các bảng khác nhau.
Nếu bạn không thích những dư thừa của định mệnh đề bộ lọc tương tự hai lần, bạn có thể rút gọn các truy vấn liên minh trong một bảng ảo trước khi lọc rằng:
SELECT code
FROM (
SELECT code_1
FROM tbl_data
UNION
SELECT code_2
FROM tbl_data
) AS DistinctCodes (code)
WHERE code IS NOT NULL;
tôi thấy cú pháp của thứ hai xấu xí hơn , nhưng nó là một cách logic. Nhưng cái nào hoạt động tốt hơn?
Tôi tạo ra một sqlfiddle đó chứng tỏ rằng tôi ưu truy vấn của SQL Server 2005 tạo ra kế hoạch thực hiện tương tự cho hai truy vấn khác nhau:
Nếu SQL Server tạo ra các kế hoạch thực hiện tương tự cho hai truy vấn, thì chúng thực tế cũng như tương đương về mặt logic.
Hãy so sánh ở trên để kế hoạch thực hiện cho truy vấn trong câu hỏi của bạn:
Các DISTINCT
khoản làm cho SQL Server 2005 thực hiện một hoạt động phân loại dư thừa, bởi vì tôi ưu truy vấn không biết rằng bất kỳ bản sao được lọc bởi DISTINCT
trong truy vấn đầu tiên sẽ được lọc theo sau UNION
sau đó.
Truy vấn này tương đương về mặt logic với hai phương pháp còn lại, nhưng thao tác dư thừa làm cho hoạt động kém hiệu quả hơn. Trên một tập dữ liệu lớn, tôi hy vọng truy vấn của bạn mất nhiều thời gian hơn để trả về một tập hợp kết quả hơn hai kết quả ở đây. Đừng dùng từ ngữ của tôi cho nó; thử nghiệm trong môi trường của riêng bạn để chắc chắn!
Cấu trúc bảng đó cho tôi cảm giác DB của bạn không được chuẩn hóa ... – gdoron
Bạn không cần 'khác biệt' trong truy vấn đầu tiên -' union' sẽ làm điều đó cho bạn. – Blorgbeard
@gdoron: Các mã tương ứng với các tên gọi khác nhau, có thể được lặp lại, tức là một bản ghi cụ thể có thể có BC và BC đối với mã 1 và 2. Chỉ định mã 1 so với 2 cũng đáng kể. Có một bảng tra cứu bảng thứ ba cho các mã khác nhau. Không phải là tốt nhất, nhưng đó là những gì tôi đang đối phó với. – regulus