sql - 对替换 id 的行进行排序

标签 sql sql-server dml

假设我有一个带有当前 ID 的表。

CREATE TABLE F
(
    id int,
    s char
)

INSERT INTO F VALUES(10)

另一个表,其中的行可以替换 ID 或更新某些内容。

CREATE TABLE M
(
    id int,
    old_id int,
    new_id int,
    type char,
    s char,
    d date
)

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”设置的 id 排序。

因此顺序为 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 的所有行
  • 然后,您可以从上一次迭代中选择 R 行来获取新 ID,并从主表中选择旧 id = 新 id 的行
  • 您最终按照 cte 中处理行的顺序对行进行排序

关于sql - 对替换 id 的行进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53592125/

相关文章:

mysql - SQL 查询,每个用户只检索两行

sql - CRYPT_GEN_RANDOM 奇怪的效果

sql - 什么是 DDL 和 DML?

sql - 我们如何合并两个查询的结果有 group by 和两个条件

c# - 如何使用延迟加载和单表继承从数据库中获取数据

sql-server - TABLOCKX 不工作

"CREATE DATABASE"语句的 C# 和 SQL Server 错误

mysql - 无法在 PHPMyAdmin 中创建触发器

database - 从一个表中获取一个值(使用条件)并在一个命令中存储在另一个表中

java - JDBC - 转换 SQL 字符串以满足 Java