摘要报告按多个日期范围分组

时间:2009-09-25 18:24:30

标签: sql sql-server tsql

我需要创建一个销售&佣金报告

基本上它是这样(请原谅SaleDate表的blatent疯狂,但我正在简化业务逻辑,实际上以这种方式实现它是有意义的)

SELECT agentName, 
       SUM(sales.Amount) AS Gross,
       SUM(sales.Amount * sales.Commission) AS Commission
FROM agent
     INNER JOIN sales ON agent.agentId = sales.agentId
WHERE sales.saleId IN (SELECT saleId FROM saleDate WHERE saleDate.myDate BETWEEN @minDate AND @maxDate)
GROUP BY agentName

所以这个查询工作得非常好。当我需要添加第二个日期范围时会出现问题。

IE,他们想要比较2007年销售额和销售额。 2008年并肩销售。

我目前基本上都有相同的查询,但我已经在sales表中添加了别名并添加了另一个

SELECT agentName, 
       SUM(sales1.Amount) AS Gross1,
       SUM(sales1.Amount * sales1.Commission) AS Commission1,
       SUM(sales2.Amount) AS Gross2,
       SUM(sales2.Amount * sales2.Commission) AS Commission2,
       SUM(sales3.Amount) AS Gross3,
       SUM(sales3.Amount * sales3.Commission) AS Commission3
FROM agent
     INNER JOIN sales1 ON agent.agentId = sales1.agentId
     INNER JOIN sales2 ON agent.agentId = sales2.agentId
     INNER JOIN sales3 ON agent.agentId = sales3.agentId
WHERE sales1.saleId IN (SELECT saleId FROM saleDate WHERE saleDate.myDate BETWEEN @minDate1 AND @maxDate1) OR
      sales2.saleId IN (SELECT saleId FROM saleDate WHERE saleDate.myDate BETWEEN @minDate2 AND @maxDate2) OR
      sales3.saleId IN (SELECT saleId FROM saleDate WHERE saleDate.myDate BETWEEN @minDate3 AND @maxDate3) 
GROUP BY agentName

然而,这个查询是永远的(在我取消它之前超过20分钟),原始版本花了不到一秒钟,如果我只使用两个组则需要9秒。

关于如何改善这种表现的任何想法?

我愿意更改此查询的设计。

4 个答案:

答案 0 :(得分:1)

如果您的第一个查询工作正常,为什么不只是UNION ALL将新日期转入第二个版本?是的,你不会得到一个透视输出,但这很容易用应用层表示代码修复。

另一种选择是使用CASE。

SELECT agentName, 
SUM (CASE WHEN saleDate.myDate BETWEEN @minDate1 AND @maxDate1 THEN sales.Amount ELSE 0 END) AS Gross1, 
SUM (CASE WHEN saleDate.myDate BETWEEN @minDate1 AND @maxDate1 THEN sales.Commission ELSE 0 END) AS Commission1,   
SUM (CASE WHEN saleDate.myDate BETWEEN @minDate2 AND @maxDate2 THEN sales.Amount ELSE 0 END) AS Gross2, 
SUM (CASE WHEN saleDate.myDate BETWEEN @minDate2 AND @maxDate2 THEN sales.Commission ELSE 0 END) AS Commission2
FROM agent
INNER JOIN sales ON agent.agentId = sales.agentId
GROUP BY agentName

答案 1 :(得分:1)

我强烈建议将其拆分为3个独立查询,然后通过UNION

合并结果

答案 2 :(得分:0)

检查您的SELECT块,它显示为:

SELECT agentName,
       SUM(sales1.Amount)AS Gross1,
       SUM(sales1.Amount * sales1.Commission)AS Commission1,
       SUM(sales2.Amount)AS Gross2,
       SUM(sales2.Amount * sales2.Commission)AS Commission2

并且您正在加入SALES3表,其值在SELECT子句中不存在。这会混淆SQL Server。删除Sales3上的INNER JOIN,它在WHERE块中的OR片段,它将起作用。

OR

将这些项添加到SELECT块。

答案 3 :(得分:0)

这只是在没有任何表格信息(大小,架构,索引)的黑暗中拍摄,但尝试在连接运算符下方移动日期过滤器:

SELECT agentName, 
           SUM(s1.Amount) AS Gross1,
           SUM(s1.Amount * s1.Commission) AS Commission1,
           SUM(s2.Amount) AS Gross2,
           SUM(s2.Amount * s2.Commission) AS Commission2
    FROM agent
    INNER JOIN (
         SELECT sales1.agentID, Commission, Amount
         FROM sales1 WHERE saleId IN (
               SELECT saleId FROM saleDate 
               WHERE saleDate.myDate BETWEEN @minDate1 AND @maxDate1)
         ) s1 ON agent.agentId = s1.agentId 
    INNER JOIN (
         SELECT sales2.agentID, Commission, Amount
         FROM sales2 WHERE saleId IN (
                SELECT saleId FROM saleDate
                WHERE saleDate.myDate BETWEEN @minDate1 AND @maxDate1)
         ) s2 ON agent.agentId = s2.agentId;
--    INNER JOIN (
--        SELECT sales3.agentID 
--         FROM sales3 WHERE saleId IN (
--              SELECT saleId FROM saleDate 
--              WHERE saleDate.myDate BETWEEN @minDate1 AND @maxDate1)
--         ) s3 ON agent.agentId = s3.agentId;