【问题标题】:How to aggregate number of customers in SQL Server?如何在 SQL Server 中聚合客户数量?
【发布时间】:2018-08-10 10:40:30
【问题描述】:

我有这样的交易数据:

| Time_Stamp          | Customer_ID | Amount | Department | Pay_Method  | Channel    |
|---------------------|-------------|--------|------------|-------------|------------|
| 2018-03-07 14:23:33 | 374856829   | 14.63  | Fruit      | Credit Card | Mobile App |

我写了一个这样的聚合过程:

INSERT INTO Days
(
    Year,
    Month,
    Day,
    Department,
    Pay_Method,
    Total_Dollars,
    Total_Transactions,
    Total_Customers
)
SELECT
    YEAR(Time_Stamp),
    MONTH(Time_Stamp),
    DAY(Time_Stamp),
    Department,
    Pay_Method,
    SUM(Amount),
    COUNT(*),
    COUNT(DISTINCT(Customer_ID))
FROM
    Transactions
GROUP BY
    YEAR(Time_Stamp),
    MONTH(Time_Stamp),
    DAY(Time_Stamp),
    Department,
    Pay_Method

这样填充数据集市表:

| Year | Month | Day | Department | Pay_Method | Total_Dollars | Total_Transactions | Total_Customers |
|------|-------|-----|------------|------------|---------------|--------------------|-----------------|
| 2018 | 3     | 7   | Home       | Cash       | 2398540.57    | 543084             | 325783          |
| 2018 | 3     | 7   | Home       | Credit     | 7458392.47    | 1587695            | 758643          |

到目前为止,一切都很好。

然后我有一些程序可以像这样为图表 UI 提供数据:

SELECT
    Year,
    Month,
    Day,
    SUM(Total_Dollars),
    SUM(Total_Transactions),
    SUM(Total_Customers)
FROM
    Days
WHERE
    IIF(@Department IS NULL, Department, @Department) AND
    IIF(@Pay_Method IS NULL, Pay_Method, @Pay_Method)
GROUP BY
    Year,
    Month,
    Day

这一切都适用于Total_TransactionsTotal_Dollars,但不适用于Total_Customers

对于 YearMonthDayDepartmentDepartmentPay_Method 的特定组合,每一行中的 Total_Customers 数字在每一行中都是正确的,但是当其中两行是加在一起,总数变得不准确,因为同一客户可能在同一日期使用不同的Department(s)Pay_Method(s) 进行了多次交易。当将天数加在一起以获得每月客户数量等时,这些数字变得更加不准确......

我认为解决方案是尝试诱使 SQL Server 将“全部”视为各种“分组依据”字段的可能值,并玩弄了分组依据和大小写,但无法弄清楚.本质上,除了包含 Year、Month、DayDepartmentPay_Method 的每个特定组合的 Days 表之外,我还需要生成 YearMonthDay、@987654342 的行@ 和 Pay_Method 被视为“任何”或“全部”。最后,我不需要生成 Year 为“any”并且指定了 MonthDay 的行(尽管它不会真的受到伤害),因为没有人关心任何一年 3 月 7 日的总数等等……

有人可以帮我编写查询以正确填充我的Days 表吗?

【问题讨论】:

  • 能否分享示例源数据及其预期输出,这将比更大的描述更有帮助
  • 如果您不想按这些字段进行过滤,请不要包含它们。这样的catch-all查询保证性能不佳。
  • 您正在描述一个典型的销售明星模式。首先,客户端语言、报告工具、Excel(例如在数据透视表中)可以添加所需的过滤条件。没有必要使用包罗万象的技巧。其次,在所有教程中,您都会看到维度,如Department、Payment_Method 可以具有基于属性的层次结构。您可以通过添加例如现金或信用卡的第二级字段来选择与所有信用卡提供商对应的所有销售。最后,销售不是天。使用单独的天/日期/日历表。这将使年度计算变得更加容易
  • 最后,您可以使用 SSAS 创建具有预先计算聚合的多维数据集。在这种情况下,All 级别只是另外一个预先计算的值。 Excel 的数据透视表等工具可以直接查询多维数据集。 SSAS 还提供日历逻辑,使逐年、逐月报告几乎微不足道

标签: sql sql-server aggregate data-warehouse


【解决方案1】:

您的问题是因为您的模型的“粒度”是错误的。粒度是事实表中详细程度的术语。

您总是希望以最详细的级别存储事实,然后才能正确汇总数据。你的第一张桌子已经到了那个时候。

与其将数据(错误地)汇总到您的第二个表中,不如简单地重写或修改该表以将您的日期/时间分解为您报告所需的字段。

顺便说一句,如果这确实代表了您的数据,我怀疑您实际上可能在交易计数中隐藏了一个错误。您可能需要比“部门”更详细的细节,我怀疑它可能是“产品”之类的概念。如果客户同时购买苹果和橙子,您的模型会怎样?

【讨论】:

  • 关于最精细的细节... 来自事务表的图表查询需要几分钟才能完成,即使有正确的索引也是如此。该表有 8000 万行。图表中需要的最详细的细节级别是 Daily,所以我有一个 Days 表,其中包含按天聚合的数据。我已经展示了我拥有的尺寸。产品是一个额外的维度,我没有为这个简化的示例列出。根据我刚刚添加的内容有什么提示吗?
猜你喜欢
  • 2017-01-29
  • 2020-06-08
  • 2022-12-11
  • 1970-01-01
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-05
相关资源
最近更新 更多