J'essaie d'obtenir la déclaration sur la récupération des lignes précédentes et suivantes d'une ligne sélectionnée.
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
Sortie requise:
L'entrée pour la procédure est order id = 10 et item id = 2 et je dois vérifier que l'article 2 est dans n'importe quel autre ordre, c'est-à-dire uniquement l'article précédent et suivant de l'enregistrement / de la commande correspondant à la date de la commande
4 Réponses :
Je pense que c'est simple, vous pouvez vérifier avec min (Id) et Max (id) avec une jointure externe gauche ou une application externe
comme
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
Faites-moi savoir si cela vous aide ou si vous rencontrez un problème avec cela ...
Cordialement,
merci mais il retourne 4 lignes mais en fait 3 lignes .. je dois trouver l'ID d'ordet = 1 et l'id de l'item = 1
ohhh j'ai manqué le paramètre orderId :) il vous suffit d'ajouter ce paramètre ...
C'est ce que vous recherchez? (Mis à jour pour refléter la modification [OrderDate] à la question)
Id OrderId ItemId Lookup 2 10 2 BE 4 2 2 D 5 3 2 DD
Requête
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
Résultat:
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;
J'ai mis à jour la question ... veuillez mettre à jour ROW_NUMBER () OVER (ORDER BY OrderDate) AS RecN,
J'ai mis à jour cela selon la modification de la question pour la colonne OrderDate et la variable @Orderid.
Mettre à jour pour donner cet ensemble de données: je vois où vous en êtes. Notez que dans CERTAINS cas, il n'y a pas de ligne avant celle donnée - donc cela ne renvoie que 2 et non 3. Ici, j'ai mis à jour la version CTE. Annulez le commentaire de la ligne OTHER pour voir 3 et non 2 car il y en a alors un avant la ligne sélectionnée avec cet Itemid.
Ajout d'une variable pour démontrer comment c'est mieux vous permettant d'obtenir 1 avant et après ou 2 avant / après si vous modifiez ce nombre (c'est-à-dire passez un paramètre) - et si moins de lignes, ou aucune n'est avant ou après, il en obtient autant que possible dans cette contrainte.
Configuration des données pour toutes les versions:
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
Version mise à jour CTE:
SELECT TOP 3
a.Id,
a.OrderId,
a.ItemId,
a.Lookup
FROM @OderDetail AS a
WHERE
a.ItemId = @ItemId
Vous voulez probablement la méthode CTE ( Voir un original à la fin de ce strong>) cependant:
Juste pour souligner, cela donne les bons résultats mais ce n'est probablement pas ce que vous recherchez car cela dépend de l'ordre des lignes et de l'ID de l'élément, pas de la ligne réelle avec ces deux valeurs:
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;
Pour résoudre ce problème, vous pouvez utiliser un ORDER BY et TOP 1 avec un UNION , un peu moche. (MISE À JOUR avec le tri par date et! = Sur l'id.)
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;
Merci pour la réponse.
Je ne vois aucune date de commande mentionnée nulle part jusqu'à présent, il aurait été bon de l'avoir dans vos données et notes de questions d'origine. Voyons si nous pouvons accueillir ce changement.
J'ai ajouté une mise à jour incluant une option CTE - qui est probablement la meilleure, le formulaire diffère légèrement des autres réponses un peu.
Merci..mais j'ai mis à jour la question..Ur Cte ainsi que la sous-requête ne fonctionne pas pour l'ID de commande 10 et l'article -id -2 pour les données données dans la question mise à jour. (L'ID de commande n'est pas toujours une séquence) toute suggestion
Pour ces numéros, je vois: Id OrderId ItemId OrderDate Lookup RowNumber 2 10 2 2018-06-11 00: 00: 00.0000000 BE 3 5 3 2 2018-06-14 00: 00: 00.0000000 DD 4 6 4 2 2018- 06-14 00: 00: 00.0000000 R 5
Une autre approche possible consiste à utiliser les fonctions LAG () et LEAD () , qui renvoient les données d'une ligne précédente et suivante du même ensemble de résultats.
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
Résultat:
-- 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)
Je ne pense pas que cela fonctionne avec des lacunes dans la colonne ID telle qu'elle est écrite
@MarkSchultheiss Je pense que cela fonctionne même avec des lacunes dans la colonne Id.
Avec les données de la question (a été mis à jour) Id OrderId ItemId OrderDate Lookup 2 10 2 2018-06-11 00: 00: 00.0000000 BE 10 10 2 2018-06-02 00: 00: 00.0000000 BE 4 2 2 2018 -06-04 00: 00: 00.0000000 D 4 2 2 2018-06-04 00: 00: 00.0000000 D 23 4 2 2018-06-14 00: 00: 00.0000000 R si vous ajoutez un intervalle ou deux
Merci ... ce code fonctionnera ... mais selon ma pensée, @ level3looper sera la meilleure solution pour la question originale (avant la mise à jour)
Quelle est votre version de serveur?
Serveur SQL 2017