SQL Server Group By Sets没有重复项

时间:2014-08-01 14:13:51

标签: sql-server performance group-by

我需要创建一个"卷起来"斜线"分组"查看我们客户的客户数据。

简化说明是,数据需要按地理(例如国家,省,市等)数据分组,并按照拥有电子邮件地址和/或电话号码的人数累计。

问题是,一个人可以在多个城市(最低级别),然后在任何更高级别(前省)计数多次。

以下是使用GROUPING SETS的示例:

DECLARE @Customer TABLE
(
    CustomerId VARCHAR(50),
    Phone BIT,
    Email BIT,
    ProvinceId VARCHAR(50),
    CityId VARCHAR(50)
)

INSERT INTO @Customer(CustomerId, Phone, Email, ProvinceId, CityId) VALUES ('Customer A', 1, NULL, 'Province A', 'City A')
INSERT INTO @Customer(CustomerId, Phone, Email, ProvinceId, CityId) VALUES ('Customer A', 1, NULL, 'Province A', 'City B')
INSERT INTO @Customer(CustomerId, Phone, Email, ProvinceId, CityId) VALUES ('Customer B', 1, 1, 'Province A', 'City B')

SELECT COUNT(Phone) PersonWithPhoneCount, COUNT(Email) PersonWithEmailCount, ProvinceId, CityId FROM @Customer
GROUP BY GROUPING SETS ((ProvinceId), (ProvinceId, CityId))

这就是结果:

----------------------------------------------------------------------------
| PersonWithPhoneCount  |  PersonWithEmailCount  |  ProvinceId  |  CityId  |
----------------------------------------------------------------------------
|                    1  |                     0  |  Province A  |  City A  |
|                    2  |                     1  |  Province A  |  City B  |
|                    3  |                     1  |  Province A  |   NULL   |
----------------------------------------------------------------------------

结果对于最低级别(城市)是正确的,但对于省级"客户A"被计算两次。我理解为什么,但有没有办法不计算"客户A"两次?

我是否必须单独对所有不同级别进行分组,还是有更好的方法?

性能也是一个主要问题,因为实时数据总计超过1亿行。

提前致谢。

1 个答案:

答案 0 :(得分:0)

即使您的数据存在错误,因为客户A无法进入城市A和城市B,这个SQL将为您提供所需的信息。我使用了ROW_NUMBER()函数,因此我只统计客户的第一次出现。

SELECT COUNT(Phone) PersonWithPhoneCount, COUNT(Email) PersonWithEmailCount, ProvinceId, CityId
FROM (
SELECT *
    ,ROW_NUMBER() OVER(PARTITION BY CustomerId 
            ORDER BY ProvinceId, CityId) Row
FROM @Customer c1
) Tmp
Where Row = 1
GROUP BY GROUPING SETS ((ProvinceId), (ProvinceId, CityId))