截至日期的最新成本值

时间:2014-02-04 22:49:43

标签: sql sql-server tsql sql-server-2012

我正在尝试生成商品费用历史记录。项目的成本值随时间而变化。为了便于报告,我正在尝试按周项目结束日期生成具有成本值的输出。我正在努力的是输出给定周结束日期的最新项目成本值,因为大部分时间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尝试而混淆它。我一直在尝试做的是交叉加入ItemDatesTable作为内联视图,以给出每周结束日期和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

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)