【问题标题】:SQL Server Group By Sets without duplicatesSQL Server Group By Sets 没有重复
【发布时间】:2014-08-01 14:13:50
【问题描述】:

我需要为我们的客户创建客户数据的“汇总”斜线“分组”视图。

一种简化的解释是,数据需要按地理(例如国家、省、市等)数据分组,并按拥有电子邮件地址和/或电话号码的人数汇总。

问题是一个人可以在多个城市(最低级别)中,然后在任何更高级别(不包括省)中被计算多次。

这是一个使用 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”?

我必须将所有不同的级别单独分组还是有更好的方法?

性能也是一个主要问题,因为实时数据加起来多达 100+ 百万行。

提前致谢。

【问题讨论】:

  • 嗨,在这种情况下,CROSS APPLY 可能是您的救星,使用 TOP 1 和按省/市分组。我只是不太清楚你所说的最低级城市是什么意思。
  • 为什么会有一个客户表,其中有两次相同的客户?这些数据是连接到另一个表的结果还是什么?
  • 嗨,史蒂夫,这是连接的结果。我们(在上面的示例中)有 3 个表:CustomerCustomerProvinceCustomerCity。关于您在下面的回答,一个人可以在多个城市(和省)。例如,数据是该人购物的地方。因此会有多个城市和省份的人)。
  • 您好 WickedFan,最低级别是指为简单起见,我在示例中省略了其他 级别。例如:大陆 --> 国家 --> 省 --> 城市。因此 City 是最低的Level。 CROSS APPLY 想法打开了几扇门,我会试一试。谢谢。

标签: sql-server performance group-by


【解决方案1】:

即使你的数据是错误的,因为客户 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))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-02
    • 2011-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-07
    • 2011-12-10
    相关资源
    最近更新 更多