GROUP BY和缺少MONTHS的值的总和

时间:2018-09-24 14:42:21

标签: sql sql-server tsql common-table-expression

我仔细阅读了许多示例,并加入了几个示例,以得出以下结论;

DECLARE @StartDate SMALLDATETIME, @EndDate SMALLDATETIME;

SELECT @StartDate = '20170930', @EndDate = '20180930';

;WITH d(d) AS 
(
  SELECT DATEADD(MONTH, n, DATEADD(MONTH, DATEDIFF(MONTH, 0, @StartDate), 0))
  FROM ( SELECT TOP (DATEDIFF(MONTH, @StartDate, @EndDate) + 1) 
    n = ROW_NUMBER() OVER (ORDER BY [object_id]) - 1
    FROM sys.all_objects ORDER BY [object_id] ) AS n
)

SELECT 
  [Period]    = CONVERT(VARCHAR(4), YEAR(d.d)) + '-' + CONVERT(VARCHAR(2), MONTH(d.d)),
  QtyTotal = ISNULL(SUM(o.QEXIT),0)
FROM d LEFT OUTER JOIN VE_STOCKTRANS AS o
  ON o.TRANSDATE >= d.d

  AND o.TRANSDATE < DATEADD(MONTH, 1, d.d)
 WHERE STOCKID = 6000 AND TRANSTYPE = 3553
GROUP BY d.d
ORDER BY d.d;

我需要获取过去一年中某商品的总销售质量。如果该商品在该特定月份没有任何销售,则该月旁边应显示0。除非提供WHERE子句,否则上述查询会执行所需的操作。添加WHERE子句以获取特定产品的数据后,没有销售的月份消失了。

如果有经验的SQL开发人员可以向我显示正确的方向,我将不胜感激。

谢谢

2 个答案:

答案 0 :(得分:1)

您需要将条件移至ON

-- ...
SELECT 
  [Period] = CONVERT(VARCHAR(4),YEAR(d.d)) +'-'+ CONVERT(VARCHAR(2), MONTH(d.d)),
  QtyTotal = ISNULL(SUM(o.QEXIT),0)
FROM d LEFT OUTER JOIN VE_STOCKTRANS AS o
  ON o.TRANSDATE >= d.d

  AND o.TRANSDATE < DATEADD(MONTH, 1, d.d)
  AND STOCKID = 6000 AND TRANSTYPE = 3553   -- here
GROUP BY d.d
ORDER BY d.d;

答案 1 :(得分:0)

一种更通用的方法是在加入之前应用过滤器。

;WITH d(d) AS 
(
  SELECT DATEADD(MONTH, n, DATEADD(MONTH, DATEDIFF(MONTH, 0, @StartDate), 0))
  FROM ( SELECT TOP (DATEDIFF(MONTH, @StartDate, @EndDate) + 1) 
    n = ROW_NUMBER() OVER (ORDER BY [object_id]) - 1
    FROM sys.all_objects ORDER BY [object_id] ) AS n
),
  o AS
(
  SELECT *
    FROM VE_STOCKTRANS
   WHERE STOCKID = 6000
     AND TRANSTYPE = 3553
)
SELECT 
  [Period] = CONVERT(VARCHAR(4), YEAR(d.d)) + '-' + CONVERT(VARCHAR(2), MONTH(d.d)),
  QtyTotal = ISNULL(SUM(o.QEXIT),0)
FROM
  d
LEFT OUTER JOIN
  o
    ON  o.TRANSDATE >= d.d
    AND o.TRANSDATE < DATEADD(MONTH, 1, d.d)
GROUP BY
  d.d
ORDER BY
  d.d;

正如您在另一个答案中所看到的,这里并非严格必要。但是,在执行FULL OUTER JOIN或其他复杂查询时,将您的源过滤到一个作用域并加入一个单独的作用域将非常有帮助。

(我总是过滤源,我讨厌块状番茄酱。)