替换 id 的订单行
Order rows that replace the id
假设我有一个 table 和当前 ID。
CREATE TABLE F
(
id int,
s char
)
INSERT INTO F VALUES(10)
和另一个 table 包含可以替换 ID 或更新某些内容的行。
CREATE TABLE M
(
id int,
old_id int,
new_id int,
type char,
s char,
d date
)
where in type 表示它是替换 id 还是更新 s。
INSERT INTO dbo.M (id, old_id, new_id, type, d, s)
VALUES
(2, 20,NULL,'U', '2018-01-01', 'a'),
(3, 10,20, 'R', '2018-01-01', NULL),
(4, 10,NULL,'U', '2018-01-01', 'b'),
(5, 20,NULL,'U', '2018-01-01', 'c'),
(6, 30,NULL,'U', '2018-01-01', 'd'),
(7, 20,30, 'R', '2018-01-01', NULL),
(8, 30,NULL,'U', '2018-01-01', 'e'),
(9, 40,NULL,'U', '2018-01-01', 'f')
如果我想对行进行排序,使得与 F 中的 id 匹配的 'U' 排在第一位,然后是与 id 匹配的 'R' ,那么接下来的行应该按照每个'R'套。
因此顺序为 4、3、2、5、7、8 或 4、3、5、2、7、8
为此你需要递归:
CREATE TABLE f(id int, s char);
INSERT INTO f(id) VALUES
(10);
CREATE TABLE m(id int, old_id int, new_id int, type char, s char, d date);
INSERT INTO m (id, old_id, new_id, type, d, s) VALUES
(2, 20, NULL, 'U', '2018-01-01', 'a'),
(3, 10, 20, 'R', '2018-01-01', NULL),
(4, 10, NULL, 'U', '2018-01-01', 'b'),
(5, 20, NULL, 'U', '2018-01-01', 'c'),
(6, 30, NULL, 'U', '2018-01-01', 'd'),
(7, 20, 30, 'R', '2018-01-01', NULL),
(8, 30, NULL, 'U', '2018-01-01', 'e'),
(9, 40, NULL, 'U', '2018-01-01', 'f');
WITH cte AS (
SELECT *, 1 AS lvl
FROM m AS base
WHERE old_id = (SELECT id FROM f)
UNION ALL
SELECT curr.*, lvl + 1
FROM m AS curr
INNER JOIN cte AS prev ON prev.type = 'R' AND curr.old_id = prev.new_id
)
SELECT *
FROM cte
ORDER BY lvl, CASE type WHEN 'U' THEN 1 WHEN 'R' THEN 2 END
结果:
| id | old_id | new_id | type | s | d | lvl |
|----|--------|--------|------|---|------------|-----|
| 4 | 10 | | U | b | 01/01/2018 | 1 |
| 3 | 10 | 20 | R | | 01/01/2018 | 1 |
| 2 | 20 | | U | a | 01/01/2018 | 2 |
| 5 | 20 | | U | c | 01/01/2018 | 2 |
| 7 | 20 | 30 | R | | 01/01/2018 | 2 |
| 6 | 30 | | U | d | 01/01/2018 | 3 |
| 8 | 30 | | U | e | 01/01/2018 | 3 |
- 递归cte的base部分包含所有包含10
的行
- 然后您继续从 prev 迭代中 selecting
R
行以从主table 其中旧 ID = 新 ID
- 您最终按照它们在 cte 中处理的顺序对行进行排序
假设我有一个 table 和当前 ID。
CREATE TABLE F
(
id int,
s char
)
INSERT INTO F VALUES(10)
和另一个 table 包含可以替换 ID 或更新某些内容的行。
CREATE TABLE M
(
id int,
old_id int,
new_id int,
type char,
s char,
d date
)
where in type 表示它是替换 id 还是更新 s。
INSERT INTO dbo.M (id, old_id, new_id, type, d, s)
VALUES
(2, 20,NULL,'U', '2018-01-01', 'a'),
(3, 10,20, 'R', '2018-01-01', NULL),
(4, 10,NULL,'U', '2018-01-01', 'b'),
(5, 20,NULL,'U', '2018-01-01', 'c'),
(6, 30,NULL,'U', '2018-01-01', 'd'),
(7, 20,30, 'R', '2018-01-01', NULL),
(8, 30,NULL,'U', '2018-01-01', 'e'),
(9, 40,NULL,'U', '2018-01-01', 'f')
如果我想对行进行排序,使得与 F 中的 id 匹配的 'U' 排在第一位,然后是与 id 匹配的 'R' ,那么接下来的行应该按照每个'R'套。
因此顺序为 4、3、2、5、7、8 或 4、3、5、2、7、8
为此你需要递归:
CREATE TABLE f(id int, s char);
INSERT INTO f(id) VALUES
(10);
CREATE TABLE m(id int, old_id int, new_id int, type char, s char, d date);
INSERT INTO m (id, old_id, new_id, type, d, s) VALUES
(2, 20, NULL, 'U', '2018-01-01', 'a'),
(3, 10, 20, 'R', '2018-01-01', NULL),
(4, 10, NULL, 'U', '2018-01-01', 'b'),
(5, 20, NULL, 'U', '2018-01-01', 'c'),
(6, 30, NULL, 'U', '2018-01-01', 'd'),
(7, 20, 30, 'R', '2018-01-01', NULL),
(8, 30, NULL, 'U', '2018-01-01', 'e'),
(9, 40, NULL, 'U', '2018-01-01', 'f');
WITH cte AS (
SELECT *, 1 AS lvl
FROM m AS base
WHERE old_id = (SELECT id FROM f)
UNION ALL
SELECT curr.*, lvl + 1
FROM m AS curr
INNER JOIN cte AS prev ON prev.type = 'R' AND curr.old_id = prev.new_id
)
SELECT *
FROM cte
ORDER BY lvl, CASE type WHEN 'U' THEN 1 WHEN 'R' THEN 2 END
结果:
| id | old_id | new_id | type | s | d | lvl |
|----|--------|--------|------|---|------------|-----|
| 4 | 10 | | U | b | 01/01/2018 | 1 |
| 3 | 10 | 20 | R | | 01/01/2018 | 1 |
| 2 | 20 | | U | a | 01/01/2018 | 2 |
| 5 | 20 | | U | c | 01/01/2018 | 2 |
| 7 | 20 | 30 | R | | 01/01/2018 | 2 |
| 6 | 30 | | U | d | 01/01/2018 | 3 |
| 8 | 30 | | U | e | 01/01/2018 | 3 |
- 递归cte的base部分包含所有包含10 的行
- 然后您继续从 prev 迭代中 selecting
R
行以从主table 其中旧 ID = 新 ID - 您最终按照它们在 cte 中处理的顺序对行进行排序