2013-06-26 2 views
1

Притворись У меня есть cupcake_rating стол:SQL Group By эквивалент

id  |  cupcake  | delicious_rating 
-------------------------------------------- 
1  |  Strawberry | Super Delicious 
2  |  Strawberry | Mouth Heaven 
3  |  Blueberry | Godly 
4  |  Blueberry | Super Delicious 

Я хочу, чтобы найти все кексы, которые имеют «супер вкусно» и рейтинг «РОТ Heaven». Я чувствую, что это легко достижимо с помощью предложения group by и, возможно, having.

Я думал:

select distinct(cupcake) 
    from cupcake_rating 
group by cupcake 
having delicious_rating in ('Super Delicious', 'Mouth Heaven') 

Я знаю, что я не могу иметь два отдельных и заявления. Я был в состоянии достичь своей цели с помощью:

select distinct(cupcake) 
    from cupcake_rating 
where cupcake in (select cupcake 
         from cupcake_rating 
        where delicious_rating = 'Super Delicious') 
    and cupcake in (select cupcake 
         from cupcake_rating 
        where delicious_rating = 'Mouth Heaven') 

Это не будет удовлетворительным, так как только я добавить третий тип рейтинга я ищу, то запрос будет занять несколько часов (есть много кекса оценок).

+0

'выбрать отдельный кекс из таблицы, где delicious_rating в (выберите delicious_ratings_here из таблицы)' – wootscootinboogie

+0

это вернет клубнику и чернику, но на самом деле я хочу только клубника – MikeB

+0

Вы можете быть удивлены, если вы запускаете тесты с различными версиями. Моя ставка будет на версиях 'IN',' EXISTS' и 'JOIN'. –

ответ

7

Вы правильно, вы можете использовать предложения HAVING; нет необходимости использовать самоподключение.

Вы хотите только кекс с двумя рейтингами, поэтому ограничиться этими двумя рейтингами, а затем проверить, что DISTINCT количество оценок равно двум:

select cupcake 
    from cupcake_rating 
where delicious_rating in ('Super Delicious', 'Mouth Heaven') 
group by cupcake 
having count(distinct delicious_rating) = 2 

SQL Fiddle

Это гораздо проще расширяемый, поскольку вам не нужно делать новое самообучение для каждого вкусного рейтинга, вам просто нужно проверить, что у вас есть номер, который вы хотите.

+0

Я снова подумал о своем ответе, не так ли ... –

+1

Да @Alex :-). Я почти перестала писать это, когда увидела, что вы записали, затем (с небольшим шоком) продолжил :-) – Ben

+0

ничего себе. очень гладкий и легкий. Отлично! – MikeB

3

Вы можете присоединиться к всем рейтингам "Super Delicious", чтобы получить оценку "Mouth Heaven" на cupcake. Таким образом, вы найдете все кексы, в которых были рейтинги «Super Delicious» и «Mouth Heaven».

SELECT DISTINCT cr.cupcake 
FROM cupcake_rating cr 
JOIN cupcake_rating cr2 
    ON cr.cupcake = cr2.cupcake 
WHERE cr.delicious_rating = 'Super Delicious' 
    AND cr2.delicious_rating = 'Mouth Heaven' 
+0

Ницца! У тебя были те же 24 строки за 9.121 секунды по сравнению с шахтой 1008.253. – MikeB

+0

Итак, когда вы делитесь этими кексами? – logixologist

1

I want to find all the cupcakes that have a 'Super Delicious' AND 'Mouth Heaven' rating

Я понимаю требования выше, означает, что кекс должен быть достигнут каждой из этих оценок, а не только один или другой. Другими словами, если все оценили кекс как Рот Небеса, это не подходило бы.

  select distinct cupcake from cupcake_ratings A where rating = 'super' 
      inner join 
      (
      select distinct cupcake from cupcake_ratings where rating = 'heaven' 
     ) x 
      on A.cupcake = x.cupcake 

доставит вам список кексов с обоими рейтингами.

P.S. Вы могли бы оптимизировать это с EXISTS, если у вас есть кексы таблицу:

  select cupcake from cupcakes 
     where exists 
     (
      select cupcake from ratings where rating = 'super' 
      and ratings.cupcake = cupcakes.cupcake 
     ) 

     and exists 
     (
      select cupcake from ratings where rating = 'heaven' 
      and ratings.cupcake = cupcakes.cupcake 
     )