2013-03-14 2 views
-2

У меня есть запрос ниже и хотел бы знать, есть ли лучший способ его настроить?Есть ли лучший способ настроить этот запрос?

MERGE INTO target_table TARGET USING 
(SELECT DISTINCT g1.column_name 
FROM test_gtt1 g1, 
test_gtt2 g2 
WHERE g1.column_name = g2.column_name 
AND g1.diff_id  IS NULL 
AND g2.diff_id  IS NULL 
UNION ALL 
SELECT DISTINCT g1.column_name 
FROM test_gtt1 g1, 
test_gtt2 g2 
WHERE 
g1.column_name = g2.column_name 
AND g1.diff_id = g2.diff_id 
AND g1.diff_id IS NOT NULL 
AND g2.diff_id IS NOT NULL 
) SOURCE ON (TARGET.column_name = SOURCE.column_name) 
WHEN MATCHED THEN 
UPDATE SET TARGET.column_name2 = 123; 
+0

Вашей логика очень смущенно. Например, зачем использовать 'select distinct ... union all ... select different' вместо 'select ... union ... select'? Короче говоря, пожалуйста, объясните свои бизнес-правила, вместо того, чтобы заставлять нас угадывать тогда из шонки кода без контекста. – APC

+2

Тюнинг - это все подробности. Какая версия Oracle? Сколько строк во всех таблицах? Сколько строк в наборе результатов USING? Сколько строк обновляется? Сколько времени это занимает? Как быстро вы хотите его запустить? Каков план объяснений? Какие столбцы индексируются? – APC

ответ

1

Это зависит от того, какие типы данных, индексы и сгенерированный план будут (это было бы полезно, если бы вы условии, что это).

Но объединение явно лишнее:

SELECT DISTINCT g1.column_name 
FROM test_gtt1 g1, 
test_gtt2 g2 
WHERE g1.column_name = g2.column_name 
AND ((g1.diff_id IS NULL 
     AND g2.diff_id IS NULL) 
    OR (g1.diff_id IS NOT NULL 
     AND g2.diff_id IS NOT NULL)) 

обновления

Это произошло со мной (при ответе на комментарий APC), что также было бы возможно, чтобы получить тот же результат, используя .. ..

SELECT DISTINCT g1.column_name 
FROM test_gtt1 g1, 
test_gtt2 g2 
WHERE g1.column_name = g2.column_name 
AND DECODE(g1.diff_id, NULL, -1, 1)=DECODE(g2.diff_id, NULL, -1, 1); 
+0

Строго говоря, этот запрос может создать другой набор результатов из опубликованного - UNION ALL not UNION - но я думаю, что ваша версия более правильна в этом конкретном случае. – APC

+0

Нет, он не вернет другой набор результатов - в исходном заявлении нет пересечения двух SELECT. – symcbean

+2

Только если 'column_name' является уникальным в обеих таблицах, чего мы не знаем. В противном случае обе стороны запроса могут вернуться, скажем, 42. Таким образом, исходный запрос будет иметь две строки для 42, и у вас будет один. Как я уже сказал, в этом случае более правильным будет один ряд. – APC

-1

Там нет необходимости для проверки diff_id is null и diff_id is not null, если вы собираетесь быть объединение этих двух наборов с UNION:

 select * from foo where bar is null 
     union all 
     select * from foo where bar is not null 

такими же, как

 select * from foo 
+1

На самом деле он хочет исключить строки, для которых diff_id имеет значение null в любой из таблиц, но не для обоих. –

+1

Я пропустил 'AND g1.diff_id = g2.diff_id'. Что делать, если g1.diff_id равно null, а g2.diff_id не является нулевым? – Tim

Смежные вопросы