admin

从另一行复制值

sql

我有一个看起来像这样的表:

  ID               AMID           DESC                  value 
  -----------------------------------------------------------------
  100              type A         AMID type A             10
  101              type B         AMID type B             18
  102              type C         AMID type C             34
  101               null            null                   4
  102               null            null                  19
  103              type D         AMID type D              6   
  103              type E            null                  7

该表包含约600万行。

现在我想要这样的结果

  ID               AMID           DESC                  value 
  -------------------------------------------------------------
  100              type A         AMID type A             10
  101              type B         AMID type B             18
  102              type C         AMID type C             34
  101              type B         AMID type B              4
  102              type C         AMID type C             19
  103              type D         AMID type D              6   
  103              type E            null                  7

当两行中的ID的AMID相等时,如果其中之一为null,则显示相同的值;如果AMID不同,则保留该值。

在此先感谢您的帮助..

干杯,

ish


阅读 168

收藏
2021-06-07

共1个答案

admin

首先,让我们设置一些适当的DDL和样本数据:

USE tempdb;
GO

CREATE TABLE dbo.AMID
(
  ID     INT, 
  AMID   VARCHAR(32), 
  [DESC] VARCHAR(32), 
  value  INT
);

INSERT dbo.AMID SELECT 100, 'type A', 'AMID type A', 10
      UNION ALL SELECT 101, 'type B', 'AMID type B', 18
      UNION ALL SELECT 102, 'type C', 'AMID type C', 34
      UNION ALL SELECT 101,  null   , null         , 4
      UNION ALL SELECT 102,  null   , null         , 19
      UNION ALL SELECT 103, 'type D', 'AMID type D', 6   
      UNION ALL SELECT 103, 'type E', null         , 7;

而不是使用不带ORDER BY的TOP(我什至不知道它的意思),您可以只选择一行用于使用partition +
order填充NULL行。在有限的样本数据中,任何ID最多只能有两行,但是如果可以有更多行,这很重要(否则,就像没有ORDER
BY的TOP一样,您将拉任意行,进行更新低于预期)。这是按AMID列中的值ID排序的,但是您可以更改此值,以使用表中的任何条件来选择每行的第一行。

;WITH src AS 
(
  SELECT ID, AMID, [DESC]
  FROM dbo.AMID 
  WHERE AMID IS NULL AND [DESC] IS NULL
),
nv AS 
(
  SELECT ID, AMID, [DESC], rn = ROW_NUMBER() OVER
  (PARTITION BY ID ORDER BY AMID) -- change this ordering accordingly
  FROM dbo.AMID 
  WHERE AMID IS NOT NULL
)
UPDATE src
  SET AMID = nv.AMID, [DESC] = COALESCE(nv.[DESC], src.[DESC])
FROM src INNER JOIN nv
ON src.ID = nv.ID
WHERE nv.rn = 1;

SELECT ID, AMID, [DESC], Value FROM dbo.AMID;

结果:

ID   AMID    DESC         value
---  ------  -----------  -----
100  type A  AMID type A  10
101  type B  AMID type B  18
102  type C  AMID type C  34
101  type B  AMID type B  4
102  type C  AMID type C  19
103  type D  AMID type D  6
103  type E  NULL         7

别忘了清理:

DROP TABLE dbo.AMID;
GO

顺便说一句,DESC是一个可怕的名字列,因为它是一个T-SQL关键字,因此 总是 必须与转义[double quotes]

2021-06-07