Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Tri basé sur les enregistrements suivants et précédents en SQL

Vous pouvez faire quelque chose comme ça.

  1. Identifiez la première et la dernière lettre de chaque parent en utilisant ROW_NUMBER() et PARTITION BY
  2. Mettre en correspondance le dernier enregistrement de l'id précédent avec le premier enregistrement du prochain id .
  3. Vérifiez si le deuxième identifiant parent contient une lettre qui correspond à la lettre sélectionnée ci-dessus
  4. Utilisez une LEFT JOIN et utilisez CASE ou ISNULL pour définir une priorité plus élevée pour un tel id enregistrement dans lequel la lettre correspondait

Requête

;WITH CTE AS 
(
SELECT id,ParentID,letter,
ROW_NUMBER()OVER(PARTITION BY parentId ORDER BY ID) first_element,
ROW_NUMBER()OVER(PARTITION BY parentId ORDER BY ID DESC) Last_element
FROM Child
), CTE2 AS 
(
SELECT c1.id,c1.parentid,c1.letter,c2.parentid as c2parentid
FROM CTE c1
INNER JOIN CTE c2
ON c1.last_element = 1
AND c2.first_element = 1
AND c1.id +1 = c2.id
), CTE3 AS 
(
SELECT C.parentid,C.id
FROM CTE2
INNER JOIN child C ON CTE2.c2parentid = C.parentid
AND C.letter = CTE2.letter
)
SELECT P.number, C.letter
FROM Child C
JOIN Parent P ON C.parentId = P.id
LEFT JOIN CTE3 ON CTE3.id = C.id
ORDER BY P.number, ISNULL(CTE3.id,0) DESC, C.letter 

Sortie

number  letter
1   A
1   C
2   C
2   B
3   B
3   D

SQL Fiddle

MODIFIER

Si vos ids ne sont pas séquentiels, vous pouvez modifier CTE1 et CTE2 comme ceci pour utiliser ROW_NUMBER()OVER(ORDER BY ID) seq_id .

;WITH CTE AS 
(
SELECT id,ParentID,letter,
ROW_NUMBER()OVER(ORDER BY ID) seq_id,
ROW_NUMBER()OVER(PARTITION BY parentId ORDER BY ID) first_element,
ROW_NUMBER()OVER(PARTITION BY parentId ORDER BY ID DESC) Last_element
FROM Child
), CTE2 AS 
(
SELECT c1.id,c1.parentid,c1.letter,c2.parentid as c2parentid
FROM CTE c1
INNER JOIN CTE c2
ON c1.last_element = 1
AND c2.first_element = 1
AND c1.seq_id + 1 = c2.seq_id
)

Le reste du code reste le même.

SQL Fiddle