按计数分组

时间:2009-06-16 15:29:10

标签: sql sql-server

假设我的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

我不能使用having子句,因为没有有效条目的品牌会从我的列表中消失(我不会看到条目Gala)。
然后我认为某种子查询应该这样做,但是我不能将外部(分组)查询的apple id链接到内部(计数)查询......

有什么想法吗?

7 个答案:

答案 0 :(得分:3)

select brand,  case when sum(hasworms)>0 then 0 else 1 end IsUnSpoiled
from apples
group by brand

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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)的索引,这个查询会超快,因为它不计算聚合,而是搜索每个品牌内的第一个被宠坏的苹果。

答案 3 :(得分:1)

SELECT  Brand, 
        1-MAX(HasWorms) AS IsUnspoiled
FROM    apples
GROUP BY Brand

答案 4 :(得分:0)

SELECT CASE WHEN SUM(HasWorms) > 0 THEN 0 ELSE 1 END AS IsUnspoiled, Brand 
FROM apples 
GROUP BY Brand

答案 5 :(得分:0)

我没有测试过这个,也许我错过了一些东西。但这不会起作用吗?

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

我假设HasWorms是一个位字段,因此是CONVERT语句。这应该返回一个品牌列表,其中包含每个品牌的变质苹果数量。您应该看到最差(最糟糕)在顶部,最好在底部。

答案 6 :(得分:0)

有很多方法可以给这只猫上皮。根据您的RDBMS,不同的查询将为您提供最佳结果。在我们的Oracle框中,此查询的执行速度比列出的所有其他查询更快,假设您在Apples表中有Brand的索引(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;