我正在尝试生成商品费用历史记录。项目的成本值随时间而变化。为了便于报告,我正在尝试按周项目结束日期生成具有成本值的输出。我正在努力的是输出给定周结束日期的最新项目成本值,因为大部分时间eff_dt日期不会与周结束日期(tran_end_dt
)对齐。
我有以下数据(简化):
create table Item( item_id int )
insert into Item values(1),(2),(3)
create table DatesTable( tran_end_dt date )
insert into DatesTable values('2014-01-04'),('2014-01-11'),('2014-01-18'),('2014-01-25')
create table ItemCostHist ( item_id int, eff_dt date, item_cost int )
insert into ItemCostHist values(1,'2014-01-01',1),(1,'2014-01-19',2),(2,'2014-01-05',1),(2,'2014-01-17',2),(3,'2014-01-01',1),(3,'2014-01-08',2),(3,'2014-01-22',3)
这应该给出:
项目
item_id
1
2
3
DatesTable(仅限周末/周六)
tran_end_dt
2014-01-04
2014-01-11
2014-01-18
2014-01-25
ItemCostHist
item_id eff_dt item_cost
1 2014-01-01 1
1 2014-01-19 2
2 2014-01-04 1
2 2014-01-17 2
3 2014-01-01 1
3 2014-01-08 2
3 2014-01-22 3
为了保持帖子的清洁,我不会因为一堆失败的SQL尝试而混淆它。我一直在尝试做的是交叉加入Item
和DatesTable
作为内联视图,以给出每周结束日期和item_id,然后根据ItemCostHist
数据加入此集合。尝试获取item_cost
eff_dt
值小于或等于tran_end_dt
时,我一直遇到麻烦。
我可以迭代地解决这个问题,但我想了解如何使用基于集合的方法解决这个问题的建议或示例。
期望的输出:
Item tran_end_dt Item Cost
1 2014-01-04 1
1 2014-01-11 1
1 2014-01-18 1
1 2014-01-25 2
2 2014-01-04 1
2 2014-01-11 2
2 2014-01-18 2
2 2014-01-25 2
3 2014-01-04 1
3 2014-01-11 2
3 2014-01-18 2
3 2014-01-25 3
答案 0 :(得分:1)
我不确定这是否是最好的方法,但这会让我得到我想要的结果。
select item_id
, tran_end_dt
, cost
from
(select distinct item_id, tran_end_dt from item cross join datestable) a
outer apply (select top 1 item_cost as cost
from itemcosthist ich
where ich.eff_dt <= a.tran_end_dt
and ich.item_id = a.item_id
order by eff_dt desc) b
order by item_id, tran_end_dt, cost
答案 1 :(得分:0)
看到这个我觉得我在这里看到的是什么,但不太确定你为什么这样做仍然是我的解决方案
SELECT item_id
,eff_dt
,item_cost
FROM ItemCostHist
UNION
SELECT item_id
,DATEADD(dd, 7-(DATEPART(dw, eff_dt)), eff_dt) [WeekEnd]
,item_cost
FROM ItemCostHist
结果集
╔═════════╦════════════╦═══════════╗
║ item_id ║ eff_dt ║ item_cost ║
╠═════════╬════════════╬═══════════╣
║ 1 ║ 2014-01-01 ║ 1 ║
║ 1 ║ 2014-01-04 ║ 1 ║
║ 1 ║ 2014-01-19 ║ 2 ║
║ 1 ║ 2014-01-25 ║ 2 ║
║ 2 ║ 2014-01-04 ║ 1 ║
║ 2 ║ 2014-01-17 ║ 2 ║
║ 2 ║ 2014-01-18 ║ 2 ║
║ 3 ║ 2014-01-01 ║ 1 ║
║ 3 ║ 2014-01-04 ║ 1 ║
║ 3 ║ 2014-01-08 ║ 2 ║
║ 3 ║ 2014-01-11 ║ 2 ║
║ 3 ║ 2014-01-22 ║ 3 ║
║ 3 ║ 2014-01-25 ║ 3 ║
╚═════════╩════════════╩═══════════╝
答案 2 :(得分:0)
M. Ali's answer有钥匙;你需要一种方法将日期转换为星期结束日期。我不相信DATEPART
系统函数,因为可能它可以根据system setting给出不同的值。
以下是类似代码的示例:
SELECT x.Date,
WeekDate = DATEADD(day, 6, DATEADD(week, DATEDIFF(week, 0, x.Date), 0))
FROM ( SELECT Date = '1904-02-13'
UNION ALL
SELECT Date = '1904-02-14'
UNION ALL
SELECT Date = '1904-02-15'
UNION ALL
SELECT Date = '1960-08-12'
UNION ALL
SELECT Date = '2013-06-04'
UNION ALL
SELECT Date = '2014-01-21'
UNION ALL
SELECT Date = '2014-01-22'
UNION ALL
SELECT Date = '2014-01-23'
UNION ALL
SELECT Date = '2014-01-26'
UNION ALL
SELECT Date = '2014-01-27'
) x
ORDER BY Date;
--Date WeekDate
------------ -----------------------
--1904-02-13 1904-02-14 00:00:00.000
--1904-02-14 1904-02-21 00:00:00.000
--1904-02-15 1904-02-21 00:00:00.000
--1960-08-12 1960-08-14 00:00:00.000
--2013-06-04 2013-06-09 00:00:00.000
--2014-01-21 2014-01-26 00:00:00.000
--2014-01-22 2014-01-26 00:00:00.000
--2014-01-23 2014-01-26 00:00:00.000
--2014-01-26 2014-02-02 00:00:00.000
--2014-01-27 2014-02-02 00:00:00.000
--(10 row(s) affected)