繁体   English   中英

SQL-跟踪每月销售额

[英]SQL - Tracking Monthly Sales

我正在写一个查询以按月汇总销售。 我的问题是我的查询仅返回销售数月的记录。 例如,我正在寻找15个月的范围。 但是在下面的示例中,只有一个特定的部分在15个月中只有3个月有销售。

我希望显示15条记录,而其他记录有0条待售。 我希望获得其他记录的原因是,我希望采用此标准差,删除记录会影响该计算。

样例代码:

SELECT I.PartNumber as PartNumber,
YEAR(O.CreateDate) as CreateDateYear,
MONTH(O.CreateDate) as CreateDateMonth,
COUNT(*) as TotalDemand
FROM OrderDetails OD
INNER JOIN Orders O on O.Id = OD.OrderId
INNER JOIN Items I on I.Id = OD.ItemId
WHERE 
O.CreateDate >= '1-1-2016' 
AND O.CreateDate <= '3-31-2017'
AND I.PartNumber = '5144831-2'
GROUP BY I.PartNumber, YEAR(O.CreateDate) , MONTH(O.CreateDate);

采样电流输出:

Part # | Year | Month | Demand
5144831-2   2017    1   1
5144831-2   2017    2   3
5144831-2   2016    3   1

所需输出:

我想要一个额外的行,例如:

5144831-2   2016    11  0

为了表明在2016年11月没有销售。

我确实有一个临时表#_date_array2,其中包含可能的月份/年份,我想我需要与LEFT JOIN结合使用的帮助。

假设您每个月都有笔销售,最简单的解决方案是切换到条件聚合:

SELECT '5144831-2' as PartNumber,
       YEAR(O.CreateDate) as CreateDateYear,
       MONTH(O.CreateDate) as CreateDateMonth,
       SUM(CASE WHEN I.PartNumber = '5144831-2' THEN 1 ELSE 0 END) as TotalDemand
FROM OrderDetails OD INNER JOIN
     Orders O 
     ON O.Id = OD.OrderId INNER JOIN
     Items I 
     ON I.Id = OD.ItemId
WHERE O.CreateDate >= '2016-01-01' AND
      O.CreateDate <= '2017-03-31'
GROUP BY YEAR(O.CreateDate) , MONTH(O.CreateDate);

注意:这是解决问题的一种方法。 更强大的解决方案包括生成日期并使用LEFT JOIN (或类似功能)。 但是,这通常是获得结果的最快方法。

如果要使用左联接,则无法直接将其与内部联接一起使用。 您可以在括号内进行内部联接,然后在外部进行左联接,以免弄乱左联接的结果。 尝试这个:

SELECT Z.PartNumber as PartNumber,
YEAR(O.CreateDate) as CreateDateYear,
MONTH(O.CreateDate) as CreateDateMonth,
COUNT(Z.OrderId) as TotalDemand
FROM Orders O 
LEFT JOIN 
(
    SELECT OrderId, PartNumber
    FROM
    OrderDetails OD 
    INNER JOIN Items I ON I.Id = OD.ItemId
    AND I.PartNumber = '5144831-2'
) Z
ON O.Id = Z.OrderId 
AND O.CreateDate >= '1-1-2016' 
AND O.CreateDate <= '3-31-2017'
GROUP BY Z.PartNumber, YEAR(O.CreateDate) , MONTH(O.CreateDate);

要获得无订单数月的0计数,请避免使用count(*)并使用上面给出的count(OrderId)。

注意-您必须确保Orders表具有所有可用的月份和年份,即,如果Orders表( Orders中的左表)中没有CreateDate值(例如2016年11月),则输出也不会产生本月的条目。

编辑:您可以尝试这样做:

SELECT Z.PartNumber as PartNumber,
YEAR(O.CreateDate) as CreateDateYear,
MONTH(O.CreateDate) as CreateDateMonth,
COUNT(O.OrderId) as TotalDemand
FROM Orders O 
RIGHT JOIN 
(
    SELECT OrderId, PartNumber
    FROM
    OrderDetails OD 
    INNER JOIN Items I ON I.Id = OD.ItemId
    AND I.PartNumber = '5144831-2'
) Z
ON O.Id = Z.OrderId 
AND O.CreateDate >= '1-1-2016' 
AND O.CreateDate <= '3-31-2017'
GROUP BY Z.PartNumber, YEAR(O.CreateDate) , MONTH(O.CreateDate);

根据您对其他帖子等的所有评论,似乎您有一个表,该表具有想要的日期范围,并且希望能够对多个/所有零件号运行分析。 因此,主要问题是,您需要在日期表和在此期间售出的零件号之间建立笛卡尔连接,以便在不售出时实现“ 0”。

;WITH cteMaxMinDates AS (
    SELECT
       MinDate = MIN(DATEFROMPARTS(CreateDateYear,CreateDateMonth,1))
       ,MaxDate = MAX(DATEFROMPARTS(CreateDateYear,CreateDateMonth,1))
    FROM
       #_date_array2
)

;WITH cteOrderDetails AS (
    SELECT
       d.CreateDateYear
       ,d.CreateDateMonth
       ,I.PartNumber
    FROM
       #_date_array2 d
       INNER JOIN Orders o
       ON d.CreateDateMonth = MONTH(o.CreateDate)
       AND d.CreateDateYear = YEAR(o.CreateDate)
       INNER JOIN OrderDetails od
       ON o.Id = od.OrderId
       INNER JOIN Items i
       ON od.ItemId = i.Id
       AND i.PartNumber = '5144831-2'
)

, cteDistinctParts AS (
    SELECT DISTINCT PartNumber
    FROM
       cteOrderDetails
)

SELECT
    d.CreateDateYear
    ,d.CreateDateMonth
    ,I.PartNumber
    ,COUNT(od.PartNumber) as TotalDemand
FROM
    #_date_array2 d
    CROSS JOIN cteDistinctParts p
    LEFT JOIN cteOrderDetails od
    ON d.CreateDateYear = od.CreateDateYear
    AND d.CreateDateMonth = od.CreateDateMonth
    AND p.PartNumber = od.PartNumber
GROUP BY
    d.CreateDateYear
    ,d.CreateDateMonth
    ,I.PartNumber

要获取所有零件号,只需删除AND i.PartNumber = '5144831-2'连接条件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM