SQL - 跟踪每月销售额
SQL - Tracking Monthly Sales
我正在编写查询以按月汇总销售额。我的问题是我的查询只有 returns 个月的销售记录。例如,我正在查看 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 月没有销售。
我确实有一个临时 table #_date_array2 可能 months/years,我想我需要帮助合并 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
(或类似功能)。但是,这通常是获得结果的最快方法。
根据您对其他帖子等的所有评论,您似乎有一个 table 具有您想要的日期范围并且您希望能够 运行 分析 multiple/all 的零件号。因此,主要问题是您需要在您的日期 table 和当时售出的零件号之间进行笛卡尔连接,以便在未售出时完成“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'
连接条件。
如果要使用left join,则不能直接与inner 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)。
注意 - 您必须确保订单 table 具有可用的所有月份和年份,即如果 Orders
中没有 CreateDate
值,例如 2016 年 11 月table(在联接中留下 table),输出也不会产生本月的条目。
编辑:
你能试试这个吗:
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);
我正在编写查询以按月汇总销售额。我的问题是我的查询只有 returns 个月的销售记录。例如,我正在查看 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 月没有销售。
我确实有一个临时 table #_date_array2 可能 months/years,我想我需要帮助合并 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
(或类似功能)。但是,这通常是获得结果的最快方法。
根据您对其他帖子等的所有评论,您似乎有一个 table 具有您想要的日期范围并且您希望能够 运行 分析 multiple/all 的零件号。因此,主要问题是您需要在您的日期 table 和当时售出的零件号之间进行笛卡尔连接,以便在未售出时完成“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'
连接条件。
如果要使用left join,则不能直接与inner 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)。
注意 - 您必须确保订单 table 具有可用的所有月份和年份,即如果 Orders
中没有 CreateDate
值,例如 2016 年 11 月table(在联接中留下 table),输出也不会产生本月的条目。
编辑: 你能试试这个吗:
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);