Créer une requête contenant des mouvements hors de la list de destinations

Given est une table de conteneurs et leur location actuel:

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 

Ce dont j'ai besoin, c'est d'une list de mouvements à partir d'une date donnée. Alors prenons le 2015/08/26 comme date souhaitée, la sortie devrait être la suivante:

 Date Container From To Scrapped ---------------------------------------------- 2015/08/26 Container1 AD 2015/08/26 Container2 BA 2015/08/26 Container3 CB 2015/08/27 Container1 DD x 2015/08/27 Container4 null B 2015/08/27 Container2 AC 2015/08/27 Container3 BA 

Créer une requête qui me donne par les enpoints est assez facile:

 select Date, Container, Location as [To], Scrapped from ContainerMovements where Date >= '2015/08/26' 

Mais comment puis-je remplir la colonne De en accédant à la ligne correspondante de l'ancienne date? Je suis sûr qu'il doit y avoir une sorte de jointure à gauche (ou si vous prenez l'ordre des colonnes), étant donné que de nouveaux conteneurs peuvent apparaître et que la colonne De peut être nulle, mais je suis actuellement simplement coincé sur ça.

La table réside dans un SQL Server 2008 R2.

Pour le rendre plus facile ici, tout est prédéfini à SQLfiddle .

Celui-ci donne les résultats attendus. Démo violon est ici .

 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] 

Sortie:

 | 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) | 

Faire une self join comme ci-dessous devrait le faire:

 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' 

Essayez ceci et voici le violon SQL

 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 

Une autre version avec 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.lf, tn.lt, 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)) 

Sortie:

 dcfts 2015-08-26 Container1 AD NULL 2015-08-26 Container2 BA NULL 2015-08-26 Container3 CB NULL 2015-08-27 Container1 DD x 2015-08-27 Container4 NULL B NULL 2015-08-27 Container2 AC NULL 2015-08-27 Container3 BA NULL