2016-04-25 4 views
2

Я передал сценарий, который имел схемуИщете более элегантный способ решения этой SQL запрос

продукта:

maker model type 
A 1232 PC 
A 1233 PC 
A 1276 Printer 
A 1298 Laptop 
A 1401 Printer 
A 1408 Printer 
A 1752 Laptop 
B 1121 PC 
B 1750 Laptop 
C 1321 Laptop 
D 1288 Printer 
D 1433 Printer 
E 1260 PC 
E 1434 Printer 
E 2112 PC 
E 2113 PC 

И запрос должен был

Получить которые производят только один тип продукта и более одной модели .

Выходные столбцы должны быть изготовителями и типами.

И вот что я придумал.

select distinct maker, type 
from Product 
where maker in (select maker 
       from Product 
       group by maker, type 
       having count(model) > 1 
       except 
       select maker 
       from 
       (
        select distinct maker, type 
        from Product 
       ) A 
       group by maker 
       having count(type) > 1) 

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


EDIT: Пожалуйста, убедитесь, что ответ только две колонки шириной, которая является

Maker, Тип

+1

Можете ли вы добавить тег для РСУБД двигателя? – amphetamachine

+0

Подзапросом может быть просто GROUP BY, с условиями в HAVING. – jarlh

ответ

1

Один метод использует exists и not exists:

select distinct p.maker, p.type 
from product p 
where exists (select 1 
       from product p2 
       where p2.maker = p.maker and p2.type = p.type and p2.model <> p.model 
      ) and 
     not exists (select 1 
        from product p2 
        where p2.maker = p.maker and p2.type <> p.type 
       ); 

В другой версии используется явное агрегирование:

select p.maker, p.type 
from product p 
where not exists (select 1 
        from product p2 
        where p2.maker = p.maker and p2.type <> p.type 
       ) 
group by p.maker, p.type 
having min(model) <> max(model); 

И, для полноты картины, вот версия, которая использует только оконные функции:

select p.model, p.type 
from (select p.*, 
      min(type) over (partition by maker) as mintype, 
      max(type) over (partition by maker) as maxtype, 
      row_number() over (partition by maker, type order by model) as seqnum, 
      count(*) over (partition by maker, type) as cnt 
     from product p 
    ) p 
where seqnum = 1 and 
     mintype = maxtype and 
     cnt > 1; 
1
select count(distinct model) as unique_model_count, 
     count(distinct type) as unique_type_count, 
     maker 
from Product 
group by maker 
having unique_type_count=1 and unique_model_count>1 
+0

_Definitely_ «правильный» ответ на этот! Однако я считаю, что необходимо включить как «создателя», так и «тип»; легко понять, что показано здесь. (Не пробовал ...) Я не на 100% - убедитесь, что имена столбцов могут быть использованы, как показано в предложении «having», но, возможно, что выражения count() должны быть повторены здесь. , .? –

+0

Правильная логика, но может выдать ошибку, если RDBMS, которая не была указана, не разрешает псевдонимы в условии наличия. –

+0

@MikeRobinson. , , Я бы сказал, что это * не * правильный ответ, потому что он не включает 'type'. –

2
SELECT maker, MIN(type) as type 
FROM Product 
GROUP BY maker 
HAVING COUNT(DISTINCT type) = 1 AND COUNT(DISTINCT model) > 1; 
+1

В большинстве баз данных это приведет к ошибке ('type' не начинается с агрегирования). В MySQL он будет возвращать только один тип на производителя. –

+0

Я знаю, но вопрос в том, какой производитель делает один тип, поэтому я думал, что это будет хорошо – Autor69

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