给出一个容器表及其当前位置:
Date Container Location Scrapped
---------------------------------------------
2015/08/25 Container1 A
2015/08/25 Container2 B
2015/08/25 Container3 C
2015/08/26 Container1 D
2015/08/26 Container2 A
2015/08/26 Container3 B
2015/08/27 Container1 D x
2015/08/27 Container4 B
2015/08/27 Container2 C
2015/08/27 Container3 A
我需要的是一个给定日期的动作列表。因此,我们将2015/08/26
作为所需日期,输出应如下所示:
Date Container From To Scrapped
----------------------------------------------
2015/08/26 Container1 A D
2015/08/26 Container2 B A
2015/08/26 Container3 C B
2015/08/27 Container1 D D x
2015/08/27 Container4 null B
2015/08/27 Container2 A C
2015/08/27 Container3 B A
创建一个通过enpoints提供给我的查询非常简单:
select
Date,
Container,
Location as [To],
Scrapped
from
ContainerMovements
where
Date >= '2015/08/26'
但是如何通过访问旧日期中的相应行来填充“发件人”列?我很确定它必须是某种左(或者如果你把列顺序称为右)加入,因为新容器可以出现并且From列可以为null,但我现在只是被卡住了在那。
该表位于SQL Server 2008 R2中。
答案 0 :(得分:1)
执行下面的self join
操作:
SELECT [Current].[Date],
Prev.Container,
Prev.Location [FROM],
[Current].Location [TO],
[Current].Scrapped
FROM
(
SELECT [Date],
Container,
Location,
Scrapped,
ROW_NUMBER() OVER (PARTITION BY Container ORDER BY [Date]) rown
FROM dbo.ContainerMovements
) Prev
JOIN
(
SELECT [Date],
Container,
Location,
Scrapped,
ROW_NUMBER() OVER (PARTITION BY Container ORDER BY [Date]) rown
FROM dbo.ContainerMovements
) [Current]
on Prev.Container = [Current].Container
AND Prev.rown + 1 = [Current].rown
AND [Current].[Date] = '2015/08/26'
答案 1 :(得分:1)
这个给出了您的预期结果。 Demo fiddle is here
DECLARE @date DATE = '20150826'
SELECT t1.[Date], t1.Container,
(SELECT TOP(1) t2.Location
FROM Table1 t2
WHERE t2.Container = t1.Container AND t2.[date] < t1.[date]
ORDER BY t2.[Date] DESC ) [from],
t1.Location [To], t1.Scrapped
FROM Table1 t1
WHERE t1.[Date] >= @date
ORDER BY t1.[Date]
输出:
| Date | Container | from | To | Scrapped |
|--------------------------|------------|--------|----|----------|
| August, 26 2015 00:00:00 | Container1 | A | D | (null) |
| August, 26 2015 00:00:00 | Container2 | B | A | (null) |
| August, 26 2015 00:00:00 | Container3 | C | B | (null) |
| August, 27 2015 00:00:00 | Container1 | D | D | x |
| August, 27 2015 00:00:00 | Container4 | (null) | B | (null) |
| August, 27 2015 00:00:00 | Container2 | A | C | (null) |
| August, 27 2015 00:00:00 | Container3 | B | A | (null) |
答案 2 :(得分:1)
试试这个,这里是SQL fiddle
SELECT [Date]
,[Container]
,[From]
,[To]
,Scrapped
FROM (
SELECT ct.DATE
,row_number() OVER (
PARTITION BY ct.Container
,ct.DATE ORDER BY frm.DATE DESC
) AS row_num
,ct.Container
,frm.Location AS [FROM]
,ct.Location AS [To]
,Scrapped = CASE
WHEN ct.Scrapped = 0
THEN ''
ELSE 'x'
END
FROM ContainerMovements ct
LEFT JOIN ContainerMovements frm ON ct.Container = frm.Container
AND frm.[Date] < ct.[Date]
WHERE ct.DATE >= '2015/08/26'
) tbl
WHERE tbl.row_num = 1
ORDER BY tbl.DATE
答案 3 :(得分:1)
FULL JOIN
的另一个版本:
DECLARE @t TABLE(d DATE, c VARCHAR(20), l CHAR(1))
DECLARE @d DATE = '2015/08/26'
INSERT INTO @t VALUES
('2015/08/25', 'Container1', 'A'),
('2015/08/25', 'Container2', 'B'),
('2015/08/25', 'Container3', 'C'),
('2015/08/26', 'Container1', 'D'),
('2015/08/26', 'Container2', 'A'),
('2015/08/26', 'Container3', 'B'),
('2015/08/27', 'Container1', 'D'),
('2015/08/27', 'Container4', 'B'),
('2015/08/27', 'Container2', 'C'),
('2015/08/27', 'Container3', 'A')
SELECT tn.d, tn.c, tp.l f, tn.l t, CASE WHEN tp.l = tn.l THEN 'x' END s
FROM @t tn
FULL JOIN @t tp ON tn.c = tp.c AND tn.d = DATEADD(dd, 1, tp.d)
WHERE tn.d IN(@d, DATEADD(dd, 1, @d))
输出:
d c f t s
2015-08-26 Container1 A D NULL
2015-08-26 Container2 B A NULL
2015-08-26 Container3 C B NULL
2015-08-27 Container1 D D x
2015-08-27 Container4 NULL B NULL
2015-08-27 Container2 A C NULL
2015-08-27 Container3 B A NULL