Ответ 1
Лучше включить код в ваш вопрос, а не неоднозначные текстовые данные, чтобы мы все работали с одними и теми же данными. Вот пример схемы и данных, которые я предположил:
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');
Как прокомментировал Blorgbeard, предложение DISTINCT
в вашем решении не является необходимым, поскольку оператор UNION
удаляет дублирующиеся строки. Существует оператор UNION ALL
, который не удаляет дубликаты, но здесь он не подходит.
Переписать ваш запрос без предложения DISTINCT
- прекрасное решение этой проблемы:
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;
Неважно, что два столбца находятся в одной таблице. Решение будет таким же, даже если столбцы находятся в разных таблицах.
Если вам не нравится избыточность указания одного и того же предложения фильтра дважды, вы можете инкапсулировать запрос объединения в виртуальную таблицу перед фильтрацией:
SELECT code
FROM (
SELECT code_1
FROM tbl_data
UNION
SELECT code_2
FROM tbl_data
) AS DistinctCodes (code)
WHERE code IS NOT NULL;
Я нахожу синтаксис второго более уродливым, но он логичнее. Но какой из них работает лучше?
Я создал sqlfiddle, который демонстрирует, что оптимизатор запросов SQL Server 2005 создает один и тот же план выполнения для двух разных запросов:
Если SQL Server генерирует один и тот же план выполнения для двух запросов, то они практически и логически эквивалентны.
Сравните вышеприведенное с планом выполнения запроса в вашем вопросе:
Предложение DISTINCT
заставляет SQL Server 2005 выполнять избыточную операцию сортировки, поскольку оптимизатор запросов не знает, что любые дубликаты, отфильтрованные с помощью DISTINCT
в первом запросе, в любом случае будут отфильтрованы UNION
позже.
Этот запрос логически эквивалентен двум другим, но избыточная операция делает его менее эффективным. На большом наборе данных, я бы ожидал, что ваш запрос займет больше времени, чтобы вернуть набор результатов, чем два здесь. Не верь мне на слово; Экспериментируйте в своей среде, чтобы быть уверенным!