我有一个更改历史记录表,如下所示
+-----+-------------+------------+------------+
| ID | BeforeValue | AfterValue | DateTime |
+-----+-------------+------------+------------+
| 255 | 396 | 400 | 01/01/2017 |
| 255 | 400 | 500 | 15/08/2017 |
| 255 | 500 | 600 | 02/06/2018 |
+-----+-------------+------------+------------+
DECLARE @tabl TABLE (ID int, BeforeValue varchar(20),AfterValue varchar(20), changeDate datetime2(0));
INSERT INTO @tabl (ID, BeforeValue, AfterValue,changeDate) VALUES
(255,'396','400', '01/01/2017'),
(255,'400','500', '08/15/2017'),
(255,'500','600', '06/02/2018');
select * from @tabl
我还有另一个存在交易数据的表,
DECLARE @output TABLE (ID int, dat datetime2(0));
INSERT INTO @output (ID, dat) VALUES
(255, '07/15/2017'),
(255, '10/29/2018'),
(255, '01/01/2015');
select * from @output
想查找给定时间段内的价值
例如输出如下
╔═════╦════════════╦══════════════╗
║ id ║ date ║ Desiredvalue ║
╠═════╬════════════╬══════════════╣
║ 255 ║ 15/07/2017 ║ 400 ║
║ 255 ║ 29/10/2018 ║ 600 ║
║ 255 ║ 01/01/2015 ║ 396 ║
╚═════╩════════════╩══════════════╝
请告诉我SQL语句是否可行, 没有任何存储过程。
答案 0 :(得分:2)
您可以使用outer apply
:
select o.*, coalesce(t.aftervalue, tfirst.beforevalue) as thevalue
from @output o outer apply
(select top (1) t.aftervalue
from @tab t
where t.id = o.id and t.datetime <= o.date
order by t.datetime desc
) t outer apply
(select top (1) t.beforevalue
from @tab t
where t.id = o.id
order by t.datetime asc
) tfirst;
答案 1 :(得分:0)
这是我要使用的方法(实际上,这是我每天在办公室使用的方法)。正如我在评论中说的那样,考虑其中一个值是实时数据,这就是我希望它来自的地方。因此,我还为实时数据添加了一个数据集:
--Live table
DECLARE @livetabl TABLE (ID int, [Value] int); --Store numerical values as what they are, numerical data
INSERT INTO @livetabl
VALUES (255,600);
--History table
DECLARE @histtabl TABLE (ID int, BeforeValue int,AfterValue int, changeDate datetime2(0));
INSERT INTO @histtabl (ID, BeforeValue, AfterValue,changeDate) VALUES
(255,396,400,'20170101'),
(255,400,500,'20170815'),
(255,500,600,'20180206');
--Your other table
DECLARE @output TABLE (ID int, dat datetime2(0));
INSERT INTO @output (ID, dat) VALUES
(255, '20170715'),
(255, '20181029'),
(255, '20150101');
SELECT l.id,
o.dat as [date],
ISNULL(h.BeforeValue,l.[value]) AS DesiredValue
FROM @output o
JOIN @livetabl l ON o.id = l.id
OUTER APPLY (SELECT TOP 1
BeforeValue
FROM @histtabl oa
WHERE oa.id = l.id
AND oa.changeDate >= o.dat
ORDER BY oa.changeDate ASC) h;