Группировать по количеству - PullRequest
1 голос
/ 16 июня 2009

Скажем, у меня есть такая таблица на моем сервере MsSql server 2005

Apples
 + Id
 + Brand
 + HasWorms

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

Так что, если бы у меня были данные

ID| Brand        | HasWorms
---------------------------
1 | Granny Smith | 1
2 | Granny Smith | 0
3 | Granny Smith | 1
4 | Jonagold     | 0
5 | Jonagold     | 0
6 | Gala         | 1
7 | Gala         | 1

Я хочу закончить с

Brand        | IsUnspoiled
--------------------------
Granny Smith | 0
Jonagold     | 1
Gala         | 0

Я полагаю, я должен сначала

select brand, numberOfSpoiles = 
    case
        when count([someMagic]) > 0 then 1
        else 0
     end
from apples
group by brand

Я не могу использовать пункт имения, потому что тогда бренды без действительных записей исчезнут из моего списка (я не вижу записи Gala).
Тогда я подумал, что подзапрос должен это сделать, но тогда я не могу связать идентификатор apple внешнего (сгруппированного) запроса с внутренним (count) запросом ...

Есть идеи?

Ответы [ 7 ]

3 голосов
/ 16 июня 2009
select brand,  case when sum(hasworms)>0 then 0 else 1 end IsUnSpoiled
from apples
group by brand
2 голосов
/ 16 июня 2009

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

таблица + данные (DML + DDL)

create table Apples(id int,brand varchar(20),HasWorms bit)

insert Apples values(1,'Granny Smith',1)
insert Apples values(2,'Granny Smith',0)
insert Apples values(3,'Granny Smith',1)
insert Apples values(4,'Jonagold',0)
insert Apples values(5,'Jonagold',0)
insert Apples values(6,'Gala',1)
insert Apples values(7,'Gala',1)

Запрос

select brand, IsSpoiled = sign(sum(convert(int,hasworms)))
from apples
group by brand

выход

brand   IsSpoiled
---------------------- 
Gala    1
Granny Smith    1
Jonagold    0
1 голос
/ 16 июня 2009
SELECT  Brand, 
        1-MAX(HasWorms) AS IsUnspoiled
FROM    apples
GROUP BY Brand
1 голос
/ 16 июня 2009
SELECT  brand,
        COALESCE(
        (
        SELECT  TOP 1 0
        FROM    apples ai
        WHERE   ai.brand = ao.brand
                AND hasWorms = 1
        ), 1) AS isUnspoiled
FROM    (
        SELECT  DISTINCT brand
        FROM    apples
        ) ao

Если у вас есть индекс на (brand, hasWorms), этот запрос будет очень быстрым, поскольку он не учитывает агрегаты, а вместо этого ищет первое испорченное яблоко в каждом бренде и останавливается.

0 голосов
/ 16 июня 2009

Есть много способов снять шкуру с этой кошки. В зависимости от вашей РСУБД, различные запросы дадут вам лучшие результаты. На нашем сервере Oracle этот запрос выполняется быстрее, чем все остальные в списке, при условии, что у вас есть индекс Brand в таблице Apples (индекс Brand, HasWorms еще быстрее, но это может быть маловероятно; в зависимости от распределения данных индекс только для HasWorms может быть самым быстрым из всех). Также предполагается, что у вас есть таблица «BrandTable», в которой есть только бренды:

SELECT Brand
     , 1 IsSpoiled
  FROM BrandTable b
 WHERE EXISTS
       ( SELECT 1
           FROM Apples a
          WHERE a.brand = b.brand
            AND a.HasWorms = 1
       )
UNION
SELECT Brand
     , 0
  FROM BrandTable b
 WHERE NOT EXISTS
       ( SELECT 1
           FROM Apples a
          WHERE a.brand = b.brand
            AND a.HasWorms = 1
       )
ORDER BY 1;
0 голосов
/ 16 июня 2009

Я не проверял это, и, возможно, я что-то упустил. Но разве это не сработает?

SELECT Brand, SUM(CONVERT(int, HasWorms)) AS SpoiledCount
FROM Apples
GROUP BY Brand
ORDER BY SpoiledCount DESC

Я предполагаю, что HasWorms - это битовое поле, отсюда и утверждение CONVERT. Это должно вернуть список брендов с количеством испорченных яблок на бренд. Вы должны увидеть худшее (наиболее испорченное) сверху и лучшее снизу.

0 голосов
/ 16 июня 2009
SELECT CASE WHEN SUM(HasWorms) > 0 THEN 0 ELSE 1 END AS IsUnspoiled, Brand 
FROM apples 
GROUP BY Brand
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...