1

ここに画像の説明を入力してください

指定された範囲から未割り当ての範囲を取得したい。たとえば、ID 43のレコードを取得することが親レコードであり、次の画像のように未割り当てのレコードを取得したい。ID44および45のレコードはID43のレコードの子です。

ここに画像の説明を入力してください

4

1 に答える 1

1

割り当てられた範囲が重複しないと仮定しました。

SQL フィドル

基本的には 4 つのクエリで構成されます。

  • Batch_number_fromFirst Query は、指定された親の Start 番号とBatch_number_fromによって並べ替えられた最初の子レコードのStart番号の間の未割り当ての番号の範囲を検索しBatch_number_fromます。
  • 2 番目のクエリは、親の子レコード間にある未割り当ての番号の範囲を検索します。
  • Batch_number_to3 番目のクエリは、指定された親の End 番号とBatch_number_toによって並べ替えられた最後の子レコードのEnd番号の間の未割り当ての番号の範囲を検索しBatch_number_fromます。
  • そして最後に、4 番目は、対応する子レコードを持たず、したがって番号が割り当てられていない親レコードを見つけます。

4 つのクエリはすべて、UNION

最初の 3 つのクエリ内には、繰り返される 2 つのサブクエリがあり、一時テーブルに移動できます。これらには と のラベルが付いChildRnkNextStartいます。

ChildRnkによって並べ替えられたすべての子レコードをランク​​付けしBatch_number_fromます。

NextStart特定の子に割り当てられた番号の次のバッチの開始番号を返しますBatch_number_from(その特定の親レコードに対して別の子がリストされている場合)。

お役に立てれば

MSSQL の場合:

SELECT 
    ChildRnk.Parent,
    Batch_Number_From AS START,
    (START-1) AS [End]
FROM 
    (SELECT
        a.Id AS Id,
        a.parent_fk AS Parent,
        a.Batch_Number_From AS START,
        a.Batch_Number_To AS 'End',
        RANK() OVER 
            (PARTITION BY a.parent_fk ORDER BY a.Batch_Number_From ASC) AS Rnk1
    FROM 
        VOUCHER_BATCH_ALLOCATION AS a
    WHERE 
        a.channel_from_fk = 2) ChildRnk
LEFT JOIN 
    (SELECT
        c.Parent,
        c.START AS NextStart,
        (Rnk1-1) AS Rnk2 
    FROM 
        (SELECT
            b.Id AS Id,
            b.parent_fk AS Parent,
            b.Batch_Number_From AS START,
            b.Batch_Number_To AS 'End',
            RANK() 
                OVER (PARTITION BY b.parent_fk ORDER BY b.Batch_Number_From ASC) AS Rnk1
        FROM 
            VOUCHER_BATCH_ALLOCATION AS b
        WHERE 
            b.channel_from_fk = 2) c
    WHERE 
        Rnk1 != 1) NextStart
ON 
    ChildRnk.Parent = NextStart.Parent
    AND Rnk1 = Rnk2
LEFT JOIN 
    VOUCHER_BATCH_ALLOCATION
ON 
    VOUCHER_BATCH_ALLOCATION.Id = ChildRnk.Parent
    AND Rnk1 = 1
WHERE 
    Batch_Number_From IS NOT NULL
    AND Batch_Number_From < START

UNION

SELECT 
    ChildRnk.Parent,
    ([End]+1) AS START,
    (NextStart-1) AS [End]
FROM 
    (SELECT
        a.Id AS Id,
        a.parent_fk AS Parent,
        a.Batch_Number_From AS START,
        a.Batch_Number_To AS 'End',
        RANK() 
             OVER (PARTITION BY a.parent_fk ORDER BY a.Batch_Number_From ASC) AS Rnk1
    FROM 
        VOUCHER_BATCH_ALLOCATION AS a
    WHERE 
        a.channel_from_fk = 2) ChildRnk
LEFT JOIN 
    (SELECT
        c.Parent,
        c.START AS NextStart,
        (Rnk1-1) AS Rnk2 
    FROM 
        (SELECT
            b.Id AS Id,
            b.parent_fk AS Parent,
            b.Batch_Number_From AS START,
            b.Batch_Number_To AS 'End',
            RANK() OVER 
                (PARTITION BY b.parent_fk ORDER BY b.Batch_Number_From ASC) AS Rnk1
        FROM 
            VOUCHER_BATCH_ALLOCATION AS b
        WHERE 
            b.channel_from_fk = 2) c
    WHERE 
        Rnk1 != 1) NextStart
ON 
    ChildRnk.Parent = NextStart.Parent
    AND Rnk1 = Rnk2
LEFT JOIN 
    VOUCHER_BATCH_ALLOCATION
ON 
    VOUCHER_BATCH_ALLOCATION.Id = ChildRnk.Parent
    AND Rnk1 = 1
WHERE 
    NextStart IS NOT NULL
    AND [End] < NextStart

UNION

SELECT 
    ChildRnk.Parent,
    ([End]+1) AS START,
    EndLimit.VeryEnd AS [End]
FROM 
    (SELECT
        a.Id AS Id,
        a.parent_fk AS Parent,
        a.Batch_Number_From AS START,
        a.Batch_Number_To AS 'End',
        RANK() OVER 
            (PARTITION BY a.parent_fk ORDER BY a.Batch_Number_From ASC) AS Rnk1
    FROM 
        VOUCHER_BATCH_ALLOCATION AS a
    WHERE 
        a.channel_from_fk = 2) ChildRnk
LEFT JOIN 
    (SELECT
        c.Parent,
        c.START AS NextStart,
        (Rnk1-1) AS Rnk2 
    FROM 
        (SELECT
            b.Id AS Id,
            b.parent_fk AS Parent,
            b.Batch_Number_From AS START,
            b.Batch_Number_To AS 'End',
            RANK() OVER 
                (PARTITION BY b.parent_fk ORDER BY b.Batch_Number_From ASC) AS Rnk1
        FROM 
             VOUCHER_BATCH_ALLOCATION AS b
        WHERE 
            b.channel_from_fk = 2) c
    WHERE 
        Rnk1 != 1) NextStart
    ON 
        ChildRnk.Parent = NextStart.Parent
        AND Rnk1 = Rnk2
LEFT JOIN 
    (SELECT
        a.Id,
        a.Batch_Number_To AS VeryEnd,
        Rnk2
    FROM 
        VOUCHER_BATCH_ALLOCATION a
    LEFT JOIN
        (SELECT
            max(ChildRnk.Parent) AS MaxParent,
            max(ChildRnk.Rnk1) AS Rnk2
        FROM 
            (SELECT
                 a.Id AS Id,
                 a.parent_fk AS Parent,
                 a.Batch_Number_From AS START,
                 a.Batch_Number_To AS 'End',
                 RANK() OVER 
                     (PARTITION BY a.parent_fk ORDER BY a.Batch_Number_From ASC) AS Rnk1
            FROM 
                VOUCHER_BATCH_ALLOCATION AS a
            WHERE 
                a.channel_from_fk = 2) ChildRnk
        GROUP BY 
            ChildRnk.Parent) c
    ON 
        c.MaxParent = a.id
    WHERE 
        a.channel_from_fk = 1) EndLimit
ON 
    EndLimit.Id = ChildRnk.Parent
    AND EndLimit.Rnk2 = Rnk1
WHERE 
    EndLimit.VeryEnd IS NOT NULL
    AND [End] < EndLimit.VeryEnd

UNION 

SELECT
    a.id AS Parent,
    a.Batch_Number_From AS START,
    a.Batch_Number_To AS [End]
FROM
    VOUCHER_BATCH_ALLOCATION a
WHERE 
    a.Channel_From_Fk = 1
    And a.id not in 
        (SELECT 
            Parent_Fk 
        FROM 
            VOUCHER_BATCH_ALLOCATION 
        WHERE 
            Channel_From_Fk=2)

編集:以下のMySql用に書き直されたスクリプト

SQL フィドル

MySQLの場合、残念ながら、 Rank()は MySQL でサポートされていないため、 Rank()関数を同じ結果を達成する SubQueryに置き換える必要がありました。

SELECT
    ChildRnk.Parent,
    Batch_Number_From AS START,
    (START-1) AS TheEnd
FROM
    (SELECT
        a.Id AS Id,
        a.parent_fk AS Parent,
        a.Batch_Number_From AS START,
        a.Batch_Number_To AS TheEnd,
        Rnk.Rank AS Rnk1
    FROM 
        VOUCHER_BATCH_ALLOCATION AS a
    LEFT JOIN
        (SELECT
            g1.id,
            g1.Parent_Fk,
            COUNT(*) AS rank
        FROM
            VOUCHER_BATCH_ALLOCATION AS g1
        JOIN
            VOUCHER_BATCH_ALLOCATION AS g2
        ON
            (g2.Batch_Number_From, g2.id) <= (g1.Batch_Number_From, g1.id)
            AND g1.Parent_Fk = g2.Parent_Fk
        GROUP BY
            g1.Parent_Fk,
            g1.Batch_Number_From
        ORDER BY
            g1.Parent_Fk,
            rank) Rnk
    ON
        Rnk.id = a.Id
    WHERE 
        a.channel_from_fk = 2) ChildRnk
LEFT JOIN
    (SELECT
        c.Parent,
        c.START AS NextStart,
        (Rnk1-1) AS Rnk2
    FROM 
        (SELECT
            b.Id AS Id,
            b.parent_fk AS Parent,
            b.Batch_Number_From AS START,
            b.Batch_Number_To AS TheEnd,
            Rnk.Rank AS Rnk1
        FROM 
            VOUCHER_BATCH_ALLOCATION AS b
        LEFT JOIN
            (SELECT
                g1.id,
                g1.Parent_Fk,
                COUNT(*) AS rank
            FROM
                VOUCHER_BATCH_ALLOCATION AS g1
            JOIN
                VOUCHER_BATCH_ALLOCATION AS g2
            ON
                (g2.Batch_Number_From, g2.id) <= (g1.Batch_Number_From, g1.id)
                AND g1.Parent_Fk = g2.Parent_Fk
            GROUP BY
                g1.Parent_Fk,
                g1.Batch_Number_From
            ORDER BY
                g1.Parent_Fk,
                rank) Rnk
        ON
            Rnk.id = b.Id
        WHERE 
            b.channel_from_fk = 2) c
    WHERE Rnk1 != 1) NextStart
ON 
    ChildRnk.Parent = NextStart.Parent
    AND Rnk1 = Rnk2
LEFT JOIN 
    VOUCHER_BATCH_ALLOCATION
ON 
    VOUCHER_BATCH_ALLOCATION.Id = ChildRnk.Parent
    AND Rnk1 = 1
WHERE 
    Batch_Number_From IS NOT NULL
    AND Batch_Number_From < START

UNION

SELECT
    ChildRnk.Parent,
    (TheEnd+1) AS START,
    (NextStart-1) AS TheEnd
FROM
    (SELECT
        a.Id AS Id,
        a.parent_fk AS Parent,
        a.Batch_Number_From AS START,
        a.Batch_Number_To AS TheEnd,
        Rnk.rank AS Rnk1
    FROM 
        VOUCHER_BATCH_ALLOCATION AS a
    LEFT JOIN
        (SELECT
            g1.id,
            g1.Parent_Fk,
            COUNT(*) AS rank
        FROM
            VOUCHER_BATCH_ALLOCATION AS g1
        JOIN
            VOUCHER_BATCH_ALLOCATION AS g2
        ON
            (g2.Batch_Number_From, g2.id) <= (g1.Batch_Number_From, g1.id)
            AND g1.Parent_Fk = g2.Parent_Fk
        GROUP BY
            g1.Parent_Fk,
            g1.Batch_Number_From
        ORDER BY
            g1.Parent_Fk,
            rank) Rnk
    ON
        Rnk.id = a.Id
    WHERE 
        a.channel_from_fk = 2) ChildRnk
LEFT JOIN
    (SELECT
        c.Parent,
        c.START AS NextStart,
        (Rnk1-1) AS Rnk2
    FROM 
        (SELECT
            b.Id AS Id,
            b.parent_fk AS Parent,
            b.Batch_Number_From AS START,
            b.Batch_Number_To AS TheEnd,
            Rnk.rank AS Rnk1
        FROM 
            VOUCHER_BATCH_ALLOCATION AS b
        LEFT JOIN
            (SELECT
                g1.id,
                g1.Parent_Fk,
                COUNT(*) AS rank
            FROM
                VOUCHER_BATCH_ALLOCATION AS g1
            JOIN
                VOUCHER_BATCH_ALLOCATION AS g2
            ON
                (g2.Batch_Number_From, g2.id) <= (g1.Batch_Number_From, g1.id)
                AND g1.Parent_Fk = g2.Parent_Fk
            GROUP BY
                g1.Parent_Fk,
                g1.Batch_Number_From
            ORDER BY
                g1.Parent_Fk,
                rank) Rnk
        ON
            Rnk.id = b.Id
        WHERE 
            b.channel_from_fk = 2) c
    WHERE 
        Rnk1 != 1) NextStart
ON 
    ChildRnk.Parent = NextStart.Parent
    AND Rnk1 = Rnk2
LEFT JOIN 
    VOUCHER_BATCH_ALLOCATION
ON 
    VOUCHER_BATCH_ALLOCATION.Id = ChildRnk.Parent
    AND Rnk1 = 1
WHERE 
    NextStart IS NOT NULL
    AND TheEnd < NextStart

UNION

SELECT
    ChildRnk.Parent,
    (TheEnd+1) AS START,
    EndLimit.VeryEnd AS TheEnd
FROM
    (SELECT
        a.Id AS Id,
        a.parent_fk AS Parent,
        a.Batch_Number_From AS START,
        a.Batch_Number_To AS TheEnd,
        Rnk.Rank AS Rnk1
    FROM 
        VOUCHER_BATCH_ALLOCATION AS a
    LEFT JOIN
        (SELECT
            g1.id,
            g1.Parent_Fk,
            COUNT(*) AS rank
        FROM
            VOUCHER_BATCH_ALLOCATION AS g1
        JOIN
            VOUCHER_BATCH_ALLOCATION AS g2
        ON
            (g2.Batch_Number_From, g2.id) <= (g1.Batch_Number_From, g1.id)
            AND g1.Parent_Fk = g2.Parent_Fk
        GROUP BY
            g1.Parent_Fk,
            g1.Batch_Number_From
        ORDER BY
            g1.Parent_Fk,
            rank) Rnk
    ON
        Rnk.id = a.Id
    WHERE 
        a.channel_from_fk = 2) ChildRnk
LEFT JOIN
    (SELECT
        c.Parent,
        c.START AS NextStart,
        (Rnk1-1) AS Rnk2
    FROM 
        (SELECT
            b.Id AS Id,
            b.parent_fk AS Parent,
            b.Batch_Number_From AS START,
            b.Batch_Number_To AS TheEnd,
            Rnk.Rank AS Rnk1
        FROM 
            VOUCHER_BATCH_ALLOCATION AS b
        LEFT JOIN
            (SELECT
                g1.id,
                g1.Parent_Fk,
                COUNT(*) AS rank
            FROM
                VOUCHER_BATCH_ALLOCATION AS g1
            JOIN
               VOUCHER_BATCH_ALLOCATION AS g2
            ON
               (g2.Batch_Number_From, g2.id) <= (g1.Batch_Number_From, g1.id)
               AND g1.Parent_Fk = g2.Parent_Fk
            GROUP BY
               g1.Parent_Fk,
               g1.Batch_Number_From
            ORDER BY
               g1.Parent_Fk,
               rank) Rnk
        ON
            Rnk.id = b.Id
        WHERE 
            b.channel_from_fk = 2) c
    WHERE 
        Rnk1 != 1) NextStart
ON 
    ChildRnk.Parent = NextStart.Parent
    AND Rnk1 = Rnk2
LEFT JOIN
    (SELECT
        a.Id,
        a.Batch_Number_To AS VeryEnd,
        Rnk2
    FROM 
        VOUCHER_BATCH_ALLOCATION a
    LEFT JOIN
        (SELECT
            max(ChildRnk.Parent) AS MaxParent,
            max(ChildRnk.Rnk1) AS Rnk2
        FROM
            (SELECT
                a.Id AS Id,
                a.parent_fk AS Parent,
                a.Batch_Number_From AS START,
                a.Batch_Number_To AS TheEnd,
                Rnk.Rank AS Rnk1
            FROM 
                VOUCHER_BATCH_ALLOCATION AS a
            LEFT JOIN
                (SELECT
                    g1.id,
                    g1.Parent_Fk,
                    COUNT(*) AS rank
                FROM
                    VOUCHER_BATCH_ALLOCATION AS g1
                JOIN
                    VOUCHER_BATCH_ALLOCATION AS g2
                ON
                    (g2.Batch_Number_From, g2.id) <= (g1.Batch_Number_From, g1.id)
                    AND g1.Parent_Fk = g2.Parent_Fk
                GROUP BY
                    g1.Parent_Fk,
                    g1.Batch_Number_From
                ORDER BY
                    g1.Parent_Fk,
                    rank) Rnk
            ON
                Rnk.id = a.Id
            WHERE 
                a.channel_from_fk = 2) ChildRnk
        GROUP BY 
            ChildRnk.Parent) c
    ON 
        c.MaxParent = a.id
    WHERE 
        a.channel_from_fk = 1) EndLimit
ON 
    EndLimit.Id = ChildRnk.Parent
    AND EndLimit.Rnk2 = Rnk1
WHERE 
    EndLimit.VeryEnd IS NOT NULL
    AND TheEnd < EndLimit.VeryEnd

UNION

SELECT
    a.id AS Parent,
    a.Batch_Number_From AS START,
    a.Batch_Number_To AS TheEnd
FROM
    VOUCHER_BATCH_ALLOCATION a
WHERE
    a.Channel_From_Fk = 1
    AND a.id NOT IN (SELECT Parent_Fk FROM VOUCHER_BATCH_ALLOCATION WHERE Channel_From_Fk=2)

お役に立てれば

于 2012-11-22T23:50:04.953 に答える