Ich versuche, die Anweisung zum Abrufen der vorherigen und nächsten Zeilen einer ausgewählten Zeile abzurufen.

Declare @OderDetail table
(
    Id int primary key,
    OrderId int,
    ItemId int,
    OrderDate DateTime2,
    Lookup varchar(15)
)

INSERT INTO @OderDetail 
VALUES  
(1, 10, 1, '2018-06-11', 'A'), 
(2, 10, 2, '2018-06-11', 'BE'), --this
(3, 2, 1, '2018-06-04', 'DR'),
(4, 2, 2, '2018-06-04', 'D'),  --this
(5, 3, 2, '2018-06-14', 'DD'), --this
(6, 4, 2, '2018-06-14', 'R');


DECLARE 
    @ItemId int = 2,
    @orderid int = 10

Erforderliche Ausgabe:

enter image description here

Die Eingabe für die Prozedur lautet Bestell-ID = 10 und Artikel-ID = 2, und ich muss überprüfen, ob Artikel-2 in einer anderen Bestellung enthalten ist, d. H. Nur der vorherige und der nächste Artikel des übereinstimmenden Datensatzes / der übereinstimmenden Bestellung zum Bestelldatum

1
Ajt 19 Jän. 2019 im 15:39

4 Antworten

Beste Antwort

Ist es das, wonach du suchst? (Aktualisiert, um die Bearbeitung von [OrderDate] für die Frage widerzuspiegeln)

Declare @OderDetail table
(
    Id int primary key,
    OrderId int,
    ItemId int,
    OrderDate DateTime2,
    Lookup varchar(15)
)

INSERT INTO @OderDetail 
VALUES  
(1, 10, 1, '2018-06-11', 'A'), 
(2, 10, 2, '2018-06-11', 'BE'), --this
(3, 2, 1, '2018-06-04', 'DR'),
(4, 2, 2, '2018-06-04', 'D'),  --this
(5, 3, 2, '2018-06-14', 'DD'), --this
(6, 4, 2, '2018-06-14', 'R');

declare @ItemId  int=2 , @orderid int = 10;

Abfrage

With cte As
(
Select ROW_NUMBER() OVER(ORDER BY OrderDate) AS RecN,
* 
From @OderDetail Where ItemId=@ItemId
) 
Select Id, OrderId, ItemId, [Lookup] From cte Where 
RecN Between ((Select Top 1 RecN From cte Where OrderId = @orderid) -1) And
((Select Top 1 RecN From cte Where  OrderId = @orderid) +1) 
Order by id

Ergebnis:

Id  OrderId ItemId  Lookup
2   10      2       BE
4   2       2       D
5   3       2       DD
1
level3looper 6 Juli 2019 im 12:22

Ein anderer möglicher Ansatz besteht darin, die Funktionen LAG() und LEAD() zu verwenden, die Daten aus einer vorherigen und einer nachfolgenden Zeile aus demselben Ergebnis zurückgeben.

-- Table
DECLARE @OrderDetail TABLE (
    Id int primary key,
    OrderId int,
    ItemId int,
    OrderDate DateTime2,
    Lookup varchar(15)
)
INSERT INTO @OrderDetail 
VALUES  
   (1, 10, 1, '2018-06-11', 'A'), 
   (2, 10, 2, '2018-06-11', 'BE'), --this
   (3, 2, 1, '2018-06-04', 'DR'),
   (4, 2, 2, '2018-06-04', 'D'),  --this
   (5, 3, 2, '2018-06-14', 'DD'), --this
   (6, 4, 2, '2018-06-14', 'R');

-- Item and order
DECLARE 
    @ItemId int = 2,
    @orderid int = 10

-- Statement    
-- Get previois and next ID for every order, grouped by ItemId, ordered by OrderDate
;WITH cte AS (
   SELECT
      Id,
      LAG(Id, 1) OVER (PARTITION BY ItemId ORDER BY OrderDate) previousId,
      LEAD(Id, 1) OVER (PARTITION BY ItemId ORDER BY OrderDate) nextId,
      ItemId,
      OrderId,
      Lookup
   FROM @OrderDetail   
)
-- Select current, previous and next order
SELECT od.*
FROM cte
CROSS APPLY (SELECT * FROM @OrderDetail WHERE Id = cte.Id) od
WHERE (cte.OrderId = @orderId) AND (cte.ItemId = @ItemId)
UNION ALL
SELECT od.*
FROM cte
CROSS APPLY (SELECT * FROM @OrderDetail WHERE Id = cte.previousId) od
WHERE (cte.OrderId = @orderId) AND (cte.ItemId = @ItemId)
UNION ALL
SELECT od.*
FROM cte
CROSS APPLY (SELECT * FROM @OrderDetail WHERE Id = cte.nextId) od
WHERE (cte.OrderId = @orderId) AND (cte.ItemId = @ItemId)

Ausgabe:

Id  OrderId ItemId  OrderDate           Lookup
2   10      2       11/06/2018 00:00:00 BE
4   2       2       04/06/2018 00:00:00 D
5   3       2       14/06/2018 00:00:00 DD
1
Zhorov 21 Jän. 2019 im 08:12

Update auf diesen Datensatz: Ich sehe, wohin Sie damit gehen. Beachten Sie, dass in EINIGEN Fällen vor der angegebenen Zeile keine Zeile steht, sodass nur 2 und nicht 3 zurückgegeben werden. Hier habe ich die CTE-Version aktualisiert. Deaktivieren Sie die ANDERE Zeile, um 3 statt 2 zu sehen, da sich dann eine vor der ausgewählten Zeile mit dieser Itemid befindet.

Es wurde eine Variable hinzugefügt, um zu demonstrieren, wie dies besser ist, damit Sie 1 vor und nach oder 2 vor / nach erhalten können, wenn Sie diese Zahl ändern (dh einen Parameter übergeben) - und wenn weniger Zeilen oder keine vor oder nach der Anzahl vorhanden sind es kann innerhalb dieser Einschränkung.

Dateneinrichtung für alle Versionen:

Declare @OderDetail table
(
    Id int primary key,
    OrderId int,
    ItemId int,
    OrderDate DateTime2,
    Lookup varchar(15)
)

INSERT INTO @OderDetail 
VALUES  
(1, 10, 1, '2018-06-11', 'A'), 
(2, 10, 2, '2018-06-11', 'BE'), --this
(3, 2, 1, '2018-06-04', 'DR'),
(4, 2, 2, '2018-06-04', 'D'),  --this
(5, 3, 2, '2018-06-14', 'DD'), --this
(9, 4, 2, '2018-06-14', 'DD'), 
(6, 4, 2, '2018-06-14', 'R'),
--(10, 10, 2, '2018-06-02', 'BE'), -- un-comment to see one before
(23, 4, 2, '2018-06-14', 'R');

DECLARE 
    @ItemId int = 2,
    @orderid int = 2;

CTE aktualisierte Version:

DECLARE @rowsBeforeAndAfter INT = 1;
;WITH cte AS (
    SELECT 
        Id,
        OrderId,
        ItemId,
        OrderDate,
        [Lookup],
        ROW_NUMBER() OVER (ORDER BY OrderDate,Id) AS RowNumber
    FROM @OderDetail
    WHERE 
        ItemId = @itemId -- all matches of this
),
myrow AS (
    SELECT TOP 1
        Id,
        OrderId,
        ItemId,
        OrderDate,
        [Lookup],
        RowNumber
    FROM cte
    WHERE 
        ItemId = @itemId 
        AND OrderId = @orderid
)
SELECT 
    cte.Id,
    cte.OrderId,
    cte.ItemId,
    cte.OrderDate,
    cte.[Lookup],
    cte.RowNumber
FROM ctE
INNER JOIN myrow
    ON ABS(cte.RowNumber - myrow.RowNumber) <= @rowsBeforeAndAfter
ORDER BY OrderDate, OrderId;

Sie möchten wahrscheinlich die CTE-Methode ( Siehe ein Original am Ende dieses ), jedoch:

Nur um darauf hinzuweisen, dies führt zu den richtigen Ergebnissen, ist aber wahrscheinlich nicht das, wonach Sie streben, da es von der Zeilenreihenfolge abhängt und die Element-ID nicht die tatsächliche Zeile mit diesen beiden Werten ist:

SELECT TOP  3
    a.Id,
    a.OrderId,
    a.ItemId,
    a.Lookup
FROM @OderDetail AS a
WHERE 
     a.ItemId = @ItemId

Um dies zu beheben, können Sie ein ORDER BY und TOP 1 mit einem hässlichen UNION verwenden. (AKTUALISIERT mit Datumssortierung und! = Auf der ID.)

SELECT 
        u.Id,
        u.OrderId,
        u.OrderDate,
        u.ItemId,
        u.Lookup
FROM (
    SELECT 
        a.Id,
        a.OrderId,
        a.OrderDate,
        a.ItemId,
        a.Lookup
    FROM @OderDetail AS a
    WHERE 
         a.ItemId = @ItemId
         AND a.OrderId = @orderid
    UNION 
    SELECT top 1
        b.Id,
        b.OrderId,
        b.OrderDate,
        b.ItemId,
        b.Lookup
    FROM @OderDetail AS b
    WHERE 
         b.ItemId = @ItemId
         AND b.OrderId != @orderid
    ORDER BY b.OrderDate desc, b.OrderId
    UNION 
    SELECT top 1
        b.Id,
        b.OrderId,
        b.OrderDate,
        b.ItemId,
        b.Lookup
    FROM @OderDetail AS b
    WHERE 
         b.ItemId = @ItemId
        AND b.OrderId != @orderid
    ORDER BY b.OrderDate asc, b.OrderId 
) AS u
ORDER BY u.OrderDate asc, u.OrderId 
1
Mark Schultheiss 21 Jän. 2019 im 11:41

Ich denke, es ist einfach, Sie können mit min (Id) und Max (id) mit linker äußerer Verknüpfung oder äußerer Anwendung überprüfen

Mögen

Declare @ItemID int = 2
Select * From @OderDetail A
Outer Apply (
    Select MIN(A2.Id) minID, MAX(A2.Id) maxID From @OderDetail A2
    Where A2.ItemId =@ItemID
) I05
Outer Apply(
    Select * From @OderDetail Where Id=minID-1
    Union All
    Select * From @OderDetail Where Id=maxID+1
    ) I052
Where A.ItemId =@ItemID Order By A.Id

Lassen Sie mich wissen, ob dies Ihnen hilft oder ob Sie Probleme damit haben ...

Grüße,

0
Nirav Raval 19 Jän. 2019 im 12:58