В общем, у меня есть запрос SELECT в сочетании с тремя независимыми запросами SELECT. Я использую операторы EXCEPT и UNION в запросе. При самостоятельном выполнении запросов я получу результаты за 1-2 секунды, но при наличии оператора EXCEPT запрос займет часы.
Структура запроса (в упрощенном виде) выглядит следующим образом:
SELECT DISTINCT FIELD_1, FIELD_2, FIELD_3 FROM MYTABLE
EXCEPT
(
SELECT DISTINCT FIELD_1, FIELD_2, FIELD_3 FROM MYTABLE WHERE XXX
UNION
SELECT DISTINCT FIELD_1, FIELD_2, FIELD_3 FROM MYTABLE WHERE YYY
)
Есть ли способы ускорить весь запрос или оператор EXCEPT в целом настолько медленный, что его следует избегать?
Ответ 1 · рейтинг 3 · Martin Smith
Вы можете сделать это с помощью GROUP BY
SELECT FIELD_1, FIELD_2, FIELD_3
FROM MYTABLE
GROUP BY FIELD_1, FIELD_2, FIELD_3
HAVING MAX(CASE WHEN (XXX) OR (YYY) THEN 1 ELSE 0 END) = 0
Ответ 2 · Yogesh Sharma
Я бы использовал NOT EXISTS вместо CTE :
WITH CTE AS (
<your union query>
)
SELECT mt.*
FROM MYTABLE mt
WHERE NOT EXISTS (SELECT 1 FROM CTE c WHERE c.FIELD_1 = mt.FIELD_1 AND . . . );
Ответ 3 · Alen.Toma
Во-первых, я бы не использовал поле для исключения, лучше использовать идентификатор, потому что его можно индексировать.
Карьер ниже будет иметь гораздо более высокую производительность.
Вот как бы я это сделал.
SELECT DISTINCT FIELD_1, FIELD_2, FIELD_3 FROM MYTABLE
where Id not in (
SELECT Id FROM MYTABLE WHERE XXX and YYY
)
Ответ 4 · Alexander Volok
Иногда полезно упростить задачу оптимизатора запросов, разделив рабочую нагрузку на несколько этапов. Особенно, если выполнение может занять несколько часов:
-- Step 1
SELECT FIELD_1, FIELD_2, FIELD_3 INTO #Step1 FROM
(
SELECT FIELD_1, FIELD_2, FIELD_3 FROM MYTABLE WHERE XXX
UNION
SELECT FIELD_1, FIELD_2, FIELD_3 FROM MYTABLE WHERE YYY
) d
-- Step 2:
SELECT DISTINCT FIELD_1, FIELD_2, FIELD_3 FROM MYTABLE
EXCEPT
SELECT FIELD_1, FIELD_2, FIELD_3 FROM #Step1
Обратите внимание, что некоторые предложения DISTINCT удалены.
Обновление, версия 3. На основе последнего обновления OP:
Tab: это та же таблица. Первый запрос в основном дает почти всю таблицу, а второй + третий запрос - это подмножества, которые мне нужно убрать из результатов первого запроса.
Я считаю, что весь запрос можно переписать так:
SELECT DISTINCT FIELD_1, FIELD_2, FIELD_3 FROM MYTABLE ext
WHERE NOT EXISTS (
SELECT * FROM (
SELECT FIELD_1, FIELD_2, FIELD_3 FROM MYTABLE
WHERE ( (XXX) OR (YYY)) -- original filter
) list
WHERE
list.FIELD_1 = ext.FIELD_1
AND list.FIELD_2 = ext.FIELD_2
AND list.FIELD_3 = ext.FIELD_3
)