2015-10-08 5 views
0

У меня вопрос в Oracle SQL.DISTINCT in JOIN

Чтобы упростить свою задачу, скажем, у меня есть две таблицы:

TAB1:    TAB2: 
Usr Fruit   Fruit Calories 
1 A    A  100 
1 A    B  200 
1 A    C  150 
1 C    D  400 
1 C    E  50 
2 A 
2 A 
2 E 

Очень важно, что есть двойные записи в TAB1. Теперь я хочу знать, калорий для USR 1. Но, присоединившись обе таблицы

SELECT TAB2.calories from TAB1 
JOIN TAB2 ON TAB1.Fruit = TAB2.Fruit 
WHERE TAB1.Usr = 1; 

Я получаю двойные результаты для двойных записей. Я мог бы, конечно, использовать различный заголовок, но есть ли возможность отличать значения (до A и C) непосредственно в соединении? Я уверен, что это улучшит мою (намного большую) производительность.

Спасибо!

+4

Если пользователь ест/использует фрукты три раза, разве он/она три раза больше калорий? –

+2

вы имеете в виду, если я ем 800 г шоколада в 4 зелья, всего 200 г? –

+0

** Почему ** важно иметь повторяющиеся записи в TAB1? Если usr 1 имеет фрукты A 3 раза, то калорий 300. Точный результат также «важен»? –

ответ

1

Try, как это:

SELECT TAB2.calories 
from (select distinct usr, fruit from TAB1) as T1 
     JOIN TAB2 ON T1.Fruit = TAB2.Fruit 
WHERE T1.Usr = 1; 
1

Вы должны сделать отчетливый до присоединиться

select sum(tab2.calories) as TotalCalories 
from (select distinct tab1.* 
     from tabl 
    ) t1 join 
    tab2 
    on t1.fruit = tab2.fruit 
where t1.user = 1; 

Кроме того, чтобы добавить значения, используйте функцию агрегации.

1

, так как вы не выбрать ничего в Табе и, возможно, у вас есть какой-то индекс полезную, я бы пойти на IN вместо объединения

SELECT TAB2.calories 
FROM TAB2 
WHERE TAB2.Fruit IN (SELECT TAB1.Fruit FROM TAB1 WHERE TAB1.Usr = 1) 

я уверен, что это один займет больше времени, но вы все еще можете попробуйте:

SELECT TAB2.calories 
FROM TAB2 
WHERE TAB2.Fruit IN (SELECT DISTINCT TAB1.Fruit FROM TAB1 WHERE TAB1.Usr = 1) 
+1

Мне сказали (но не знаю из первых рук), что первый способ предпочтительнее, поскольку CBO оптимизирует это в полусоединении, если это необходимо, тем самым устраняя группировку/сортировку, связанную с отдельной. По результатам, они, безусловно, дадут одинаковые результаты – Hambone

+0

@ Хамбоун, да, мой комментарий не был таким ясным. изменил его. –

+0

Возможно, это фальшивка, но мне любопытно, почему этот ответ был проголосован. Решение будет работать, правильно объяснено и эффективно. Если кто-то может объяснить, я хотел бы знать, для моего собственного образования, что не так с ответом. – Hambone

5

Я большой поклонник полусоединения. Для таблиц это малое, это не имеет значения, но для больших таблиц это может иметь большое значение:

select 
    tab2.calories 
from tab2 
where exists (
    select null 
    from tab1 
    where tab1.fruit = tab2.fruit and tab1.usr = 1 
) 
+0

Это отличное решение, которое я должен сказать! +1 :) –