我想从指定的范围获取未分配的范围,例如,获取id为43的记录是父记录,我想获得未分配的记录,如下图所示,id为44和45的记录是id为43的记录的子记录
答案 0 :(得分:1)
我假设分配范围不重叠。
基本上它由四个查询组成。
Batch_number_from
排序的第一个子记录的父母指定的起始编号Batch_number_from
和起始编号Batch_number_from
之间找到任何范围的未分配编号。Batch_number_to
和Batch_number_to
排序的最后一个子记录的结束号码Batch_number_from
。使用UNION
在前三个查询中有两个子查询重复,因此可以移动到临时表。这些标记为ChildRnk
和NextStart
。
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,我必须用SubQuery替换Rank()函数,这将实现相同的结果,因为MySQL不支持unfortunatley Rank()。
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)
希望这有助于