4

到目前为止,我有以下内容。

DECLARE @Table Table (ID int, Value1 varchar(50), Value2 varchar(50), Value3 varchar(50))
INSERT INTO @Table (ID, Value1, Value2, Value3)
SELECT 1, 'One', 'Uno', 'FIrst'
UNION ALL
SELECT 2, 'Two', 'Dos', 'Second'
UNION ALL
SELECT 3, 'One', 'Uno', 'Third'
UNION ALL
SELECT 4, 'Three', 'Tres', 'Fourth'

SELECT *, CASE
            WHEN COUNT(*) OVER (PARTITION BY  Value1, Value2) > 1 THEN 1
            ELSE 0
        END AS Duplicate  FROM @Table

这给了我重复。我想再导出一个列,它将重复记录的连接值作为“第一 - 第三”(两列)

预期产出

ID  Value1  Value2  Value3  Duplicate   Value3
1   One     Uno     FIrst   1           First - Third
3   One     Uno     Third   1           First - Third
4   Three   Tres    Fourth  0           NULL
2   Two     Dos     Second  0           NULL 
4

3 回答 3

4

不幸的是,SQL Server 没有聚合连接功能,但您可以使用 xml 技巧:

select
   t.ID, t.Value1, t.Value2, t.Value3,
   case
       when count(*) over(partition by t.Value1, t.Value2) > 1 then 1
       else 0
   end as Duplicate,
   stuff(
       (
          select ' - ' + TT.Value3
          from @Table as TT
          where TT.Value1 = t.Value1 and TT.Value2 = t.Value2
          for xml path(''), type
       ).value('.', 'nvarchar(max)')
   , 1, 3, '') as Value3_Dupl
from @Table as t

sql fiddle demo

如果您只需要显示重复项Duplicate = 1,我认为最好使用 cte (或子查询),它更干净一点:

;with cte as (
    select *, count(*) over(partition by Value1, Value2) as cnt
    from @Table
)
select
   t.ID, t.Value1, t.Value2, t.Value3,
   case
       when cnt > 1 then 1
       else 0
   end as Duplicate,
   case
       when cnt > 1 then
         stuff(
             (
                select ' - ' + TT.Value3
                from @Table as TT
                where TT.Value1 = t.Value1 and TT.Value2 = t.Value2
                for xml path(''), type
             ).value('.', 'nvarchar(max)')
         , 1, 3, '')
    end as Value3_Dupl
from cte as t

sql fiddle demo

只是快速说明 - 我使用typeafterfor xml path('')然后将连接字符串与value('.', 'nvarchar(max)')函数一起使用,这不仅仅是因为我喜欢它。如果你不以这种方式使用solutin,而只是使用隐式转换为varchar,'<'或'&'之类的字符将无法正确转换。

于 2013-10-03T17:30:26.317 回答
1
SELECT *, 
    CASE
        WHEN COUNT(*) OVER (PARTITION BY  Value1, Value2) > 1 THEN 1
        ELSE 0
    END AS Duplicate, 

    CASE WHEN COUNT(*) OVER (PARTITION BY  Value1, Value2) > 1 
        THEN STUFF((SELECT ' - ' + Value3 
                    FROM @Table T 
                    WHERE T.Value1 = V.Value1 
                    AND T.Value2 = V.Value2 
                    FOR XML PATH('')), 
                   1, 3, '')
        ELSE NULL 
    END
FROM @Table V

SQL 小提琴示例

于 2013-10-03T17:30:59.883 回答
1

试试这个:

DECLARE @Table Table (ID int, Value1 varchar(50), Value2 varchar(50), Value3 varchar(50))
INSERT INTO @Table (ID, Value1, Value2, Value3)
SELECT 1, 'One', 'Uno', 'FIrst'
UNION ALL
SELECT 2, 'Two', 'Dos', 'Second'
UNION ALL
SELECT 3, 'One', 'Uno', 'Third'
UNION ALL
SELECT 4, 'Three', 'Tres', 'Fourth'


;WITH CTE_MY
AS
(
SELECT *, 
CASE
    WHEN COUNT(*) OVER (PARTITION BY  Value1, Value2) > 1 THEN 1
    ELSE 0
END AS Duplicate
FROM @Table
)

DECLARE @Table Table (ID int, Value1 varchar(50), Value2 varchar(50), Value3 varchar(50))
INSERT INTO @Table (ID, Value1, Value2, Value3)
SELECT 1, 'One', 'Uno', 'FIrst'
UNION ALL
SELECT 2, 'Two', 'Dos', 'Second'
UNION ALL
SELECT 3, 'One', 'Uno', 'Third'
UNION ALL
SELECT 4, 'Three', 'Tres', 'Fourth'


;WITH CTE_MY
AS
(
SELECT *, 
CASE
    WHEN COUNT(*) OVER (PARTITION BY  Value1, Value2) > 1 THEN 1
    ELSE 0
END AS Duplicate
FROM @Table
)

SELECT *, 
CASE WHEN (SELECT CAST(M1.Value3 AS VARCHAR(MAX)) + ' - ' +CAST(M2.Value3 AS VARCHAR(MAX)) FROM CTE_MY M2 WHERE M1.Value1 = M2.Value1 AND M1.ID <> M2.ID) = 'Third - FIrst' THEN 'FIrst - Third' ELSE 
(SELECT CAST(M1.Value3 AS VARCHAR(MAX)) + ' - ' +CAST(M2.Value3 AS VARCHAR(MAX)) FROM CTE_MY M2 WHERE M1.Value1 = M2.Value1 AND M1.ID <> M2.ID) END VALUE3
FROM CTE_MY M1
于 2013-10-08T11:33:26.857 回答