SQL 查询以根据交易日期加入数据以获得本月和上月的成本
SQL query to join data based on transaction date to get this month's & previous month's cost
我有一个交易数据集,其中包含 product_id、cost_unit、日期等列。产品成本每个月都在变化。我想要一个 table 具有以下结构
Product | Cost_from_this_Month | Cost_from_Previous_month
每个月可以有多个产品行,但该特定月份的费用是相同的。也就是说,一个月的费用是固定的。如何构建查询以获得我想要的结果?
我知道如何获取最近的费用:
SELECT * FROM (
SELECT Product, Cost_Unit
, Date
, zrank = row_number() OVER ( PARTITION BY Product ORDER BY Date DESC)
FROM MY_Table
) a where a.zrank = 1
谁能帮帮我?
如果您使用 SQL Server 2012 或更高版本,条件聚合和 lag()
函数如何?
select year(date), month(date), max(cost_unit) as thismonthcost,
lag(max(cost_unit)) over (order by year(date), month(date)) as lastmonthcost
from my_table
group by year(date), month(date)
如果您使用 SQL Server 2012 或更高版本,可以使用 LEAD
或 LAG
:
DECLARE @Products TABLE (
Product VARCHAR(100),
Cost_Unit MONEY,
[Date] DATETIME
)
INSERT @Products VALUES
('Widget', 10, '1/1/2014'),
('Widget', 12, '2/1/2014'),
('Widget', 15, '3/1/2014'),
('Widget', 17, '4/1/2014'),
('Gizmo', 20, '1/1/2014'),
('Gizmo', 25, '2/1/2014'),
('Gizmo', 26, '3/1/2014'),
('Gizmo', 27, '4/1/2014')
SELECT
Product,
[Date],
Products.Cost_Unit AS [Cost_This_Month],
LAG(Products.Cost_Unit) OVER (PARTITION BY Product ORDER BY [Date]) AS [Cost_Last_Month]
FROM @Products Products
ORDER BY Product, [Date] DESC
这里的输出产生:
Product Date Cost_This_Month Cost_Last_Month
--------------- ----------------------- --------------------- ---------------------
Gizmo 2014-04-01 00:00:00.000 27.00 26.00
Gizmo 2014-03-01 00:00:00.000 26.00 25.00
Gizmo 2014-02-01 00:00:00.000 25.00 20.00
Gizmo 2014-01-01 00:00:00.000 20.00 NULL
Widget 2014-04-01 00:00:00.000 17.00 15.00
Widget 2014-03-01 00:00:00.000 15.00 12.00
Widget 2014-02-01 00:00:00.000 12.00 10.00
Widget 2014-01-01 00:00:00.000 10.00 NULL
如果您没有使用 SQL 2012 或更高版本并且无法使用这些新功能,那么带有 ROW_NUMBER 的 CTE 也将为您提供以下功能:
;WITH CTE AS (
SELECT
Product,
[Date],
Cost_Unit,
ROW_NUMBER() OVER (PARTITION BY Product ORDER BY [Date] DESC) AS RowNum
FROM @Products
)
SELECT
CM.Product,
CM.Product,
CM.Cost_Unit AS [Cost_This_Month],
LM.Cost_Unit AS [Cost_Last_Month]
FROM CTE CM
LEFT OUTER JOIN CTE LM
ON CM.Product = LM.Product
AND CM.RowNum = LM.RowNum - 1
UPDATE 更新以说明一个月内的多笔交易。这假设该月的最后一笔交易是您当月使用的费用(例如,如果 5 月 1 日为 10 美元,5 月 5 日为 11 美元,则 5 月的 Cost_Unit 为 11 美元)。
-- LAG Solution
SELECT
Product,
[Date],
Products.Cost_Unit AS [Cost_This_Month],
LAG(Products.Cost_Unit) OVER (
PARTITION BY Product ORDER BY [Date]) AS [Cost_Last_Month]
FROM (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY Product, YEAR([Date]), MONTH([Date])
ORDER BY [Date] DESC) AS RowNum
FROM @Products
) Products
WHERE RowNum = 1
ORDER BY Product, [Date] DESC
-- ROW_NUMBER() Solution
;WITH CTE AS (
SELECT
Product,
[Date],
Cost_Unit,
ROW_NUMBER() OVER (PARTITION BY Product ORDER BY [Date] DESC) AS RowNum
FROM (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY Product, YEAR([Date]), MONTH([Date])
ORDER BY [Date] DESC) AS RowNum
FROM @Products
) Products
WHERE Products.RowNum = 1
)
SELECT
CM.Product,
CM.[Date],
CM.Cost_Unit AS [Cost_This_Month],
LM.Cost_Unit AS [Cost_Last_Month]
FROM CTE CM
LEFT OUTER JOIN CTE LM
ON CM.Product = LM.Product
AND CM.RowNum = LM.RowNum - 1
我有一个交易数据集,其中包含 product_id、cost_unit、日期等列。产品成本每个月都在变化。我想要一个 table 具有以下结构
Product | Cost_from_this_Month | Cost_from_Previous_month
每个月可以有多个产品行,但该特定月份的费用是相同的。也就是说,一个月的费用是固定的。如何构建查询以获得我想要的结果?
我知道如何获取最近的费用:
SELECT * FROM (
SELECT Product, Cost_Unit
, Date
, zrank = row_number() OVER ( PARTITION BY Product ORDER BY Date DESC)
FROM MY_Table
) a where a.zrank = 1
谁能帮帮我?
如果您使用 SQL Server 2012 或更高版本,条件聚合和 lag()
函数如何?
select year(date), month(date), max(cost_unit) as thismonthcost,
lag(max(cost_unit)) over (order by year(date), month(date)) as lastmonthcost
from my_table
group by year(date), month(date)
如果您使用 SQL Server 2012 或更高版本,可以使用 LEAD
或 LAG
:
DECLARE @Products TABLE (
Product VARCHAR(100),
Cost_Unit MONEY,
[Date] DATETIME
)
INSERT @Products VALUES
('Widget', 10, '1/1/2014'),
('Widget', 12, '2/1/2014'),
('Widget', 15, '3/1/2014'),
('Widget', 17, '4/1/2014'),
('Gizmo', 20, '1/1/2014'),
('Gizmo', 25, '2/1/2014'),
('Gizmo', 26, '3/1/2014'),
('Gizmo', 27, '4/1/2014')
SELECT
Product,
[Date],
Products.Cost_Unit AS [Cost_This_Month],
LAG(Products.Cost_Unit) OVER (PARTITION BY Product ORDER BY [Date]) AS [Cost_Last_Month]
FROM @Products Products
ORDER BY Product, [Date] DESC
这里的输出产生:
Product Date Cost_This_Month Cost_Last_Month
--------------- ----------------------- --------------------- ---------------------
Gizmo 2014-04-01 00:00:00.000 27.00 26.00
Gizmo 2014-03-01 00:00:00.000 26.00 25.00
Gizmo 2014-02-01 00:00:00.000 25.00 20.00
Gizmo 2014-01-01 00:00:00.000 20.00 NULL
Widget 2014-04-01 00:00:00.000 17.00 15.00
Widget 2014-03-01 00:00:00.000 15.00 12.00
Widget 2014-02-01 00:00:00.000 12.00 10.00
Widget 2014-01-01 00:00:00.000 10.00 NULL
如果您没有使用 SQL 2012 或更高版本并且无法使用这些新功能,那么带有 ROW_NUMBER 的 CTE 也将为您提供以下功能:
;WITH CTE AS (
SELECT
Product,
[Date],
Cost_Unit,
ROW_NUMBER() OVER (PARTITION BY Product ORDER BY [Date] DESC) AS RowNum
FROM @Products
)
SELECT
CM.Product,
CM.Product,
CM.Cost_Unit AS [Cost_This_Month],
LM.Cost_Unit AS [Cost_Last_Month]
FROM CTE CM
LEFT OUTER JOIN CTE LM
ON CM.Product = LM.Product
AND CM.RowNum = LM.RowNum - 1
UPDATE 更新以说明一个月内的多笔交易。这假设该月的最后一笔交易是您当月使用的费用(例如,如果 5 月 1 日为 10 美元,5 月 5 日为 11 美元,则 5 月的 Cost_Unit 为 11 美元)。
-- LAG Solution
SELECT
Product,
[Date],
Products.Cost_Unit AS [Cost_This_Month],
LAG(Products.Cost_Unit) OVER (
PARTITION BY Product ORDER BY [Date]) AS [Cost_Last_Month]
FROM (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY Product, YEAR([Date]), MONTH([Date])
ORDER BY [Date] DESC) AS RowNum
FROM @Products
) Products
WHERE RowNum = 1
ORDER BY Product, [Date] DESC
-- ROW_NUMBER() Solution
;WITH CTE AS (
SELECT
Product,
[Date],
Cost_Unit,
ROW_NUMBER() OVER (PARTITION BY Product ORDER BY [Date] DESC) AS RowNum
FROM (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY Product, YEAR([Date]), MONTH([Date])
ORDER BY [Date] DESC) AS RowNum
FROM @Products
) Products
WHERE Products.RowNum = 1
)
SELECT
CM.Product,
CM.[Date],
CM.Cost_Unit AS [Cost_This_Month],
LM.Cost_Unit AS [Cost_Last_Month]
FROM CTE CM
LEFT OUTER JOIN CTE LM
ON CM.Product = LM.Product
AND CM.RowNum = LM.RowNum - 1