【问题标题】:Complex SQL MERGE/PIVOT Not Ordering as Desired复杂的 SQL MERGE/PIVOT 未按预期排序
【发布时间】:2013-10-10 10:55:27
【问题描述】:

我有以下两张表; ICD 使用

创建
CREATE TABLE ICD ([E] VARCHAR(8), [I] VARCHAR(8));
GO
INSERT INTO ICD ([E], [I])
VALUES
    ('1', 'B1'),
    ('1', 'A1'),
    ('1', 'C23q'),
    ('1', '32Dq'),
    ('2', 'FFFq'),
    ('2', 'ERRE'),
    ('2', 'E'),
    ('3', 'WQWW'),
    ('3', 'WQ'),
    ('4', 'AAAA');
GO

其中O 给出了将列I 插入另一个表的顺序。第二个表是Episode,这是使用

创建的
CREATE TABLE Episode ([EpiNum] VARCHAR(4), [SomeField] VARCHAR(4), 
                      [DX1] VARCHAR(10), [DX2] VARCHAR(10), 
                      [DX3] VARCHAR(10), [DX4] VARCHAR(10));
GO
INSERT INTO Episode ([EpiNum], [SomeField], [DX1], [DX2], [DX3], [DX4])
VALUES
    ('1', 'Test', '', '', '', ''),
    ('2', 'Test', '', '', '', ''), 
    ('3', 'Test', '', '', '', '');
GO

所以我的目标是将ICDI 列的值插入DXn 字段,具体取决于是否有要插入的值。忍受我;我有这个工作使用

MERGE INTO [Episode] AS T 
USING (
   SELECT [EpiNum], [1], [2], [3], [4] 
   FROM 
      ( 
          SELECT *, ROW_NUMBER() 
            OVER (PARTITION BY [EpiNum] ORDER BY [I]) AS rn
          FROM [ICD] 
      ) AS p
    PIVOT 
   (
      MAX([I]) 
      FOR rn IN ([1], [2], [3], [4])) AS p2
   ) AS S
ON T.[EpiNum] = S.[EpiNum] 
WHEN MATCHED THEN
   UPDATE SET [DX1] = S.[1], [DX2] = S.[2], [DX3] = S.[3], [DX4] = S.[4];

这会产生一个看起来像

Episode
EpiNum  Test    DX1     DX2     DX3     DX4
'1'     'Test'  '32Dq'  'A1'    'B2'    'C23q'  
'2'     'Test'  'E'     'ERRE'  'FFFq'  null
'3'     'Test'  'WQ'    'WQWW'  null    null
'4'     'Test'  'AAAA'  null    null    null

太棒了!等等...不太好,PIVOT/MERGE 中的ORDER BY 正在破坏数据的原始顺序。我试图通过添加另一列 O 来解决这个问题,该列包含我想要的顺序,所以 ICD

定义
CREATE TABLE ICD ([E] VARCHAR(8), [I] VARCHAR(8), [O] INT);
GO
INSERT INTO ICD ([E], [I], [O])
VALUES
    ('1', 'B1.2', 1),
    ('1', 'A1.2', 2),
    ('1', 'C23q', 3),
    ('1', '32Dq', 4),
    ('2', 'FFFq', 1),
    ('2', 'ERRE', 2),
    ('3', 'WQWW', 1),
    ('4', 'AAAA', 1);
GO

我正在尝试使用ORDER BYO

MERGE INTO [Episode] AS T 
USING (
    SELECT [E], [1], [2], [3], [4] 
    FROM 
        ( 
             SELECT *, ROW_NUMBER() 
               OVER (PARTITION BY [E] ORDER BY [O]) AS rn
             FROM [ICD] 
        ) AS p
    PIVOT 
    (
       MAX([I]) 
       FOR rn IN ([1], [2], [3], [4])) AS p2
    ) AS S
ON T.[E] = S.[E] 
WHEN MATCHED THEN
    UPDATE SET [DX1] = S.[1], [DX2] = S.[2], [DX3] = S.[3], [DX4] = S.[4];

但我收到以下消息

MERGE 语句多次尝试更新或删除同一行。当目标行匹配多个源行时会发生这种情况。 MERGE 语句不能多次 UPDATE/DELETE 目标表的同一行。优化 ON 子句以确保目标行最多匹配一个源行,或使用 GROUP BY 子句对源行进行分组。

如何修改上述MERGE/PIVOT 才能正确订购?

感谢您的宝贵时间

【问题讨论】:

    标签: sql merge sql-server-2008-r2 sql-order-by pivot


    【解决方案1】:

    好吧,您的示例运行不正确,因为您在创建表和查询之间混合了 [E]Epinum 列。但是假设这些实际上是相同的列,那么您的第二个查询不起作用,因为您实际上并没有在 [E] 列上进行分组。试试这个:

    MERGE INTO [Episode] AS T 
    USING (
        SELECT [E], [1], [2], [3], [4] 
        FROM 
            ( 
                 SELECT [E], [I], ROW_NUMBER() 
                   OVER (PARTITION BY [E] ORDER BY [O]) AS rn
                 FROM [ICD] 
            ) AS p
        PIVOT 
        (
           MAX([I]) 
           FOR rn IN ([1], [2], [3], [4])) AS p2
        ) AS S
    ON T.[Epinum] = S.[E] 
    WHEN MATCHED THEN
        UPDATE SET [DX1] = S.[1], [DX2] = S.[2], [DX3] = S.[3], [DX4] = S.[4];
    

    现在,我真的不明白您为什么使用 ROW_NUMBER() 而不是简单地使用 [O] 列(值对我来说似乎相同),但这两种方式都有效。

    【讨论】:

    • 这是动态 SQL 查询/SP 的一部分。事实上,当我为这个问题简化事情时,EpiNum/E 值中的不匹配是一个错误。 ROW_NUMBER() 用作 DX 类型列的数量是动态的,并且是动态决定的。
    • @Killercam 我假设这么多。无论如何,修复是不使用SELECT * FROM [ICD],因为您正在使用ROW_NUMBER 重复[O] 列中的值。使用SELECT 列出其中一个(不是两者);这样你的PIVOT 就会正确分组
    • 很好的答案,感谢您的宝贵时间。完美……在截止日期前有点恼火——我开始看不到明显的事情了。再次感谢您的宝贵时间...
    猜你喜欢
    • 1970-01-01
    • 2014-06-30
    • 1970-01-01
    • 2011-02-25
    • 2015-11-06
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多