代码之家  ›  专栏  ›  技术社区  ›  Kvasi

为替换ID的行排序

  •  2
  • Kvasi  · 技术社区  · 7 年前

    假设我有一个具有当前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
    )
    

    类型中的位置指示它是替换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

    1 回复  |  直到 7 年前
        1
  •  4
  •   Salman Arshad    7 年前

    您将需要递归:

    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的一部分包含所有包含10的行
    • 然后选择 R 行从 普雷夫 迭代以获取新ID并从主表中选择行,其中旧ID=新ID
    • 最后,按照CTE中处理行的顺序对行进行排序。