2016-06-13 34 views
0

可以說我有聲明,像這樣表變量...SQL服務器:ROW_NUMBER()OVER上表變量修改重複列

DECLARE @LocalTable TABLE 
(
    IdField NVARCHAR(MAX), 
    NameField NVARCHAR(MAX) 
) 

我填充它是這樣的...

INSERT INTO @LocalTable 
SELECT 
    IdColumn, 
    NameColumn 
FROM SourceTable 

NameColumn在源表中可能有重複的值,因此本地表中的NameField將具有相同的重複值。

而且我們說,我想插入本地表到目標表是這樣的...

INSERT INTO TargetTable (NewIdColumn, NewNameColumn) 
    SELECT 
     IdField, 
     NameField 
    FROM 
     @LocalTable 

但是:NewNameColumnTargetTableUNIQUE約束,從而重複導致異常。

我想申請這個例子中,

ROW_NUMBER() OVER(PARTITION BY NameField ORDER BY NameField) 

使得NameField附加/與表示其重複的數位後綴。

我有這方面的工作的例子,可以選擇正確附加價值,但我不能得到這個在這樣的更新語句工作:提前

UPDATE localtable 
SET NameField = AppendedNameField 
FROM @LocalTable AS localtable 

SELECT 
    CONCAT(Ref.NameField, ROW_NUMBER() OVER (PARTITION BY Ref.NameField 
              ORDER BY Source.IdField)), * 
FROM 
    @LocalTable AS Source 
INNER JOIN 
    @LocalTable AS Ref ON Ref.NameField = Source.NameField 
         AND Ref.IdField != Source.IdField 

感謝。

+0

有你無法選擇不同的理由嗎?如果是這樣,您需要決定要加載哪些數據,並使用聚合函數或其他方法來獲取數據。 –

+0

您可以在此處執行許多操作 - 選擇不同的,使用row_number,並且可能優先於另一個,還可以添加索引忽略重複鍵。你需要添加一些注意事項,所以答案將是有意義的。 –

回答

4

如果我已經明白了,你正在嘗試做的。

WITH CTE AS 
(
SELECT 
CONCAT(NameField, ROW_NUMBER() 
    OVER(PARTITION BY NameField ORDER BY IdField)) AS NewName, * 
FROM @LocalTable 
) 
UPDATE 
CTE SET Name = NewName 

如果你只希望它做重複的名字,你可以使用添加COUNT(*) OVER (PARTITION BY Name)到CTE和條件邏輯。

+0

絕對的傳奇! –

0

只需將標識字段添加到臨時表。

DECLARE @LocalTable TABLE 
(
ix int identity primary key, 
IdField NVARCHAR(MAX), 
NameField NVARCHAR(MAX) 
) 

Insert into @LocalTable(IdColumn, NameColumn) 
SELECT 
IdColumn, 
NameColumn 
FROM SourceTable 
-- Make sure same names are consecutive in the table 
ORDER BY NameColumn 

集名稱列像這樣:

update lt set 
NameColumn = NameColumn 
-- Add a number based on the ix, minus the lowest ix entry for the same name 
+ cast(
    (select lt.ix - min(lt2.ix) + 1 
    from @localTable lt2 where lt2.name = lt.name) 
as nvarchar(10)) 
from @LocalTable lt 
-- Only do those with duplicated names 
where lt.NameColumn in (
    select NameColumn from @localtable group by NameColumn having count(1) > 1 
) 
1

您不一定需要更新表格,插入時是否可以添加後綴?

DECLARE @LocalTable TABLE (IdField INT, NameField VARCHAR(50)); 
INSERT @LocalTable VALUES (1, 'Not Duplicate'), (2, 'Duplicate'), (3, 'Duplicate'); 

INSERT INTO TargetTable (NewIdColumn, NewNameColumn) 
SELECT IdField, 
     CONCAT(NameField, 
      CASE WHEN COUNT(*) OVER(PARTITION BY NameField) > 1 
       THEN ROW_NUMBER() OVER(PARTITION BY NameField ORDER BY IdField) 
       ELSE '' 
      END) 
FROM @LocalTable 
ORDER BY IdField; 

或者,您也可以通過簡單的包裝上面選擇的子查詢和更新更新:

DECLARE @LocalTable TABLE (IdField INT, NameField VARCHAR(50)); 
INSERT @LocalTable VALUES (1, 'Not Duplicate'), (2, 'Duplicate'), (3, 'Duplicate'); 

UPDATE t 
SET  NameField = NewNameField 
FROM  
(
    SELECT IdField, NameField, 
      NewNameField = CONCAT(NameField, 
           CASE WHEN COUNT(*) OVER(PARTITION BY NameField) > 1 
            THEN ROW_NUMBER() OVER(PARTITION BY NameField ORDER BY IdField) 
            ELSE '' 
           END) 
    FROM @LocalTable 
) AS t; 

SELECT * FROM @LocalTable; 
0

起初,考慮使用臨時表,而不是臨時變量。
其次,試圖通過一些小的改變NVARCHAR(MAX),如INT
下面是代碼包含在名稱字段中唯一的值:

CREATE TABLE #LocalTable 
(
    IdField NVARCHAR(MAX), 
    NameField NVARCHAR(MAX) 
) 

INSERT INTO #LocalTable 
VALUES (1,'A'), (2,'B'), (3,'B') 

INSERT INTO TargetTable 
(
    NewIdColumn, 
    NewNameColumn 
) 
SELECT IdField, NameField 
FROM #LocalTable 
WHERE IdField in (
    SELECT MIN(IdField) FROM #LocalTable 
    GROUP BY NameField 
); 

注意的重複的記錄「IdField」將忽略並且不插入到目標表中。

0

嘗試使用下面的代碼:

WITH TargetTable AS(
SELECT *, 
     ROW_NUMBER() OVER(PARTITION BY Ref.NameField ORDER BY Source.IdField) AS UniqueID 

FROM @LocalTable AS L 
), 
UpdatedData AS(
    SELECT Source.NameField, 
      ROW_NUMBER() OVER(PARTITION BY Ref.NameField ORDER BY Source.IdField) AS UniqueID, 
      CONCAT(Ref.NameField, ROW_NUMBER() OVER(PARTITION BY Ref.NameField ORDER BY Source.IdField)) AS AppendedNameField 
    FROM @LocalTable AS Source 
    INNER JOIN @LocalTable AS Ref ON Ref.NameField = Source.NameField AND Ref.IdField != Source.IdField 
) 
UPDATE T 
SET NameField=U.AppendedNameField 
FROM TargetTable AS T 
JOIN UpdatedData AS U ON T.NameField=U.NameField AND T.UniqueID=U.UniqueID;