【问题标题】:Advanced SQL: Sum of sales between a date range高级 SQL:日期范围内的销售额总和
【发布时间】:2019-07-17 07:39:43
【问题描述】:

我正在尝试获取某个日期范围内特定产品的销售额总和。不幸的是,两个日期结果的销售额总和是相同的。正确的,2019/01/01 的总销售额为 5000,第二天 2019/01/02 的总销售额为 3000。结果显示这两天的总销售额为 8000。这是错误的。有没有高手可以帮忙改进一下这个查询?

Declare @BusinessDate datetime ='2019-01-01'
Declare @end datetime ='2019-01-02'
DECLARE @StoreId int = 100
SELECT  [Terminals].[Id] AS [TerminalId],
        [Terminals].[StoreId],
        [EOD].[Id] AS [EODId],
        SUM([Sales].[SalesAmount]) AS [SalesAmount],
        [EOD].BusinessDate
FROM    [CEPP]..[Stores] WITH (NOLOCK)
        INNER JOIN [CEPP]..[Terminals] WITH (NOLOCK)
 ON     [Stores].[Id] = [Terminals].[StoreId]
        AND [Terminals].[MWorkFlowStatusId] = 2
        AND ([Terminals].[MStatusId] = 1
        OR ([Terminals].[MStatusId] = 0
        AND [Terminals].[SuspendedDate] > @BusinessDate ))
        LEFT JOIN [EndOfDays] AS [EOD] WITH (NOLOCK)
 ON     [Terminals].[Id] = [EOD].[TerminalId]
        AND [EOD].[BusinessDate] >= @BusinessDate and [EOD].[BusinessDate]<=@end
        CROSS APPLY (
            SELECT SUM([Products].[Deno]) AS [SalesAmount]
            FROM [SalesOrders] AS [SO] WITH (NOLOCK)
                INNER JOIN [SalesTransactions] AS [ST] WITH (NOLOCK)
            ON  [SO].[Id] = [ST].[SalesOrderId]
                LEFT JOIN [VoidOrders] AS [VO] WITH (NOLOCK)
                INNER JOIN [VoidTransactions] AS [VT] WITH (NOLOCK)
            ON  [VO].[Id] = [VT].[VoidOrderId]
            ON  [SO].[DealerId] = [VO].[DealerId]
                AND [SO].[StoreId] = [VO].[StoreId]
                AND [SO].[TerminalId] = [VO].[TerminalId]
                AND [ST].[ProductId] = [VT].[ProductId]
                AND [ST].[SerialNo] = [VT].[SerialNo]
                AND [ST].[BusinessDate] = [VT].[BusinessDate]
                AND [VT].[MVoidTypeId] = 1
                INNER JOIN [CEPP].[dbo].[Products] WITH (NOLOCK)
            ON  [ST].[ProductId] = [Products].[Id]
            WHERE [EOD].[Id] IS NOT NULL
                AND [VT].[SerialNo] IS NULL
                AND [SO].[TerminalId] = [Terminals].[Id]
                AND [ST].[BusinessDate] >= @BusinessDate and [ST].[BusinessDate] <= @end
        ) AS [Sales]
WHERE  [Stores].[DealerId] = 1 AND (@StoreId IS NULL OR [Terminals].[StoreId] = @StoreId)
GROUP BY [Terminals].[Id], [Terminals].[StoreId], [EOD].[Id], [Stores].[Code], [Terminals].[Code],[EOD].BusinessDate
ORDER BY ISNULL([EOD].[Id], 0), [Stores].[Code], [Terminals].[Code]

我得到的意外结果是:

TerminalId  StoreId   EODId   SalesAmount   BusinessDate
  21598      100     5427531    8000.00    2019-01-01 00:00:00.000
  21598      100     5427532    8000.00    2019-01-02 00:00:00.000

结果应该是这样的:

TerminalId  StoreId   EODId   SalesAmount   BusinessDate
  21598      100     5427531    5000.00    2019-01-01 00:00:00.000
  21598      100     5427532    3000.00    2019-01-02 00:00:00.000

【问题讨论】:

  • 尝试将所有 BusinessDate 列转换为 Date CAST(BusinessDate AS DATE),看看这是否会给您所需的结果。

标签: sql sql-server tsql stored-procedures


【解决方案1】:

从我一目了然并且没有测试数据的情况下,SUM([Products].[Deno]) 正在 CROSS APPLY 中执行,而与外部查询中的任何 GROUP BY 无关。因此,为什么您要让每个输出行的 SUM([Sales].[SalesAmount]) 等于 8000。

重构 CROSS APPLY 子查询以聚合 SUM([Products].[Deno]) 关于 GROUP BY 并通过 GROUP BY 谓词连接回主表到您的外部查询。

【讨论】:

    【解决方案2】:

    AND [EOD].[BusinessDate] >= @BusinessDate 和 [EOD].[BusinessDate]

    这部分在我看来非常可疑。我觉得应该是这样的

    [EOD].[BusinessDate] = [Sales].[Date]

    如果这不能解决您的问题,请向我们提供用于创建表和测试数据的脚本。这样就更容易调查查询。

    【讨论】:

      猜你喜欢
      • 2013-09-28
      • 2017-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-06
      相关资源
      最近更新 更多