sql >> データベース >  >> RDS >> Sqlserver

SQL の次のレコードと前のレコードに基づく並べ替え

    このようなことができます。

    <オール>
  1. ROW_NUMBER() を使用して、各親の最初と最後の文字を識別します および PARTITION BY
  2. 前の ids の最後のレコードに一致 次の ids の最初のレコードで .
  3. 2 番目の親 ID に、上で選択した文字と一致する文字があるかどうかを確認してください
  4. LEFT JOIN を使用する CASE を使用します または ISNULL そのような ids に高い優先度を設定するには 文字が一致したレコード
  5. クエリ

    ;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 
    

    出力

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

    SQL フィドル

    編集

    あなたの ids CTE1 を変更できます および CTE2 このように 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
    )
    

    コードの残りの部分は同じままです。

    SQL フィドル




    1. Mysqlのクロスデータベーストリガー

    2. 可能なPostgres行ロックを解放する方法は?

    3. SQLServer2012で機能しないT-SQLCTEマテリアライズ手法

    4. 2つのテーブル間のサブクエリに基づくOracleSQLの更新