如何修改下面的代码,使最终的群集字符串仅具有不重复前一个字符串的ErrorCodes,因此对于第3行,仅返回一个C(跳过第二个C),对于第1行,则返回A,C,A,B(由于相邻重复而跳过第二个A)。
DECLARE @table1 TABLE
(
[Case] INT,
ErrorCode CHAR(1),
[Date] varchar(20)
);
INSERT INTO @table1
VALUES
(1, 'A', '2018-01-25'),
(1, 'A', '2018-01-15'),
(1, 'C', '2018-01-15'),
(1, 'A', '2018-01-15'),
(1, 'A', '2018-01-15'),
(1, 'B', '2018-01-15'),
(2, 'D', '2018-01-26'),
(2, 'A', '2018-01-26'),
(2, 'D', '2018-01-25'),
(2, 'C', '2018-01-24'),
(2, 'C', '2018-01-24');
SELECT *
FROM @table1;
SELECT tabel2.[Case],
tabel2.[Date],
STUFF(
(
SELECT ', ' + ErrorCode
FROM @table1 t1
WHERE t1.[Case] = tabel2.[Case]
AND t1.[Date] = tabel2.[Date]
FOR XML PATH('')
),
1,
1,
''
) AS [ErrorCode]
FROM
(SELECT DISTINCT [Case], [Date] FROM @table1) AS tabel2
ORDER BY tabel2.[Case],
tabel2.[Date];
答案 0 :(得分:1)
这就是我的方法。
首先,最好在表中有一个主键或唯一约束,该标识符可以唯一地标识每一行,即设置理论-101 :)。如果您不这样做,我以为是,这就是我添加PK或行号的方法:
;WITH Mytable AS
(
SELECT [case], [date], ErrorCode, ROW_NUMBER() OVER(ORDER BY (select NULL)) as rn
FROM table1
)
SELECT * FROM Mytable
现在,我们知道每行的顺序非常重要,这是您的任务所必需的,请使用子查询查找每行的下一个值:
,nextTable AS
(
SELECT *, (SELECT errorcode
FROM Mytable mt2
WHERE mt2.rn = mt1.rn+1
AND mt1.[Case] = mt2.[case]
AND mt1.[date] = mt2.[date]) as NextErrorCode
FROM Mytable mt1
)
最后,使用CASE子句将它们相互比较,如果重复,则将其消除:
,final AS
(
SELECT[case], [date],
CASE WHEN ErrorCode = ISNULL(NextErrorCode, '') THEN NULL ELSE ErrorCode END as NewErrorCode
FROM nextTable
WHERE CASE WHEN ErrorCode = ISNULL(NextErrorCode, '') THEN NULL ELSE ErrorCode END IS NOT NULL
)
最简单的部分是,按您希望的方式将行连接成字符串:
SELECT @str = COALESCE(@str + ',','') + NewErrorCode
FROM final
WHERE [case] = @case AND [date] = @date
最终代码如下:
CREATE FUNCTION dbo.fn_groupConcat
(
@case int,
@date date
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @str varchar(200)
;WITH Mytable AS
(
SELECT [case], [date], ErrorCode, ROW_NUMBER() OVER(ORDER BY (select NULL)) as rn
FROM table1
)
,nextTable AS
(
SELECT *, (SELECT errorcode
FROM Mytable mt2
WHERE mt2.rn = mt1.rn+1 AND mt1.[Case] = mt2.[case] AND mt1.[date] = mt2.[date]) as NextErrorCode
FROM Mytable mt1
)
,final AS
(
SELECT[case], [date],
CASE WHEN ErrorCode = ISNULL(NextErrorCode, '') THEN NULL ELSE ErrorCode END as NewErrorCode
FROM nextTable
WHERE CASE WHEN ErrorCode = ISNULL(NextErrorCode, '') THEN NULL ELSE ErrorCode END IS NOT NULL
)
SELECT @str = COALESCE(@str + ',','') + NewErrorCode
FROM final
WHERE [case] = @case AND [date] = @date
RETURN(@str)
END
将该函数应用于您的表:
SELECT [case], [date], dbo.fn_groupConcat([case],[date]) as ErrorCode
FROM table1
GROUP BY [case], [date]
---------------------------------
|case | date | ErrorCode |
---------------------------------|
| 1 | 2018-01-15 | A,C,A,B |
| 1 | 2018-01-25 | A |
| 2 | 2018-01-24 | C |
| 2 | 2018-01-25 | D |
| 2 | 2018-01-26 | D,A |
答案 1 :(得分:0)
您刚刚错过了INNER
DISTINCT
:
SELECT DISTINCT ', ' + ErrorCode
FROM @table1 t1
WHERE t1.[Case] = tabel2.[Case]
AND t1.[Date] = tabel2.[Date]
FOR XML PATH('')
答案 2 :(得分:0)
您可以尝试以下查询。
SELECT [Case],
[Date]
,STUFF((SELECT ', ' + CAST(ErrorCode AS VARCHAR(10)) [text()]
FROM @table1
WHERE [Case] = t.[Case] and [Date] = t.[Date]
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,2,' ') List_Output
FROM @Table1 t
GROUP BY [Case], [Date]
您可以找到实时演示here。
要仅获取唯一值,您需要使用Distinct
关键字,如下所示。
SELECT [Case],
[Date]
,STUFF((SELECT Distinct ', ' + CAST(ErrorCode AS VARCHAR(10)) [text()]
FROM @table1
WHERE [Case] = t.[Case] and [Date] = t.[Date]
FOR XML PATH(''), TYPE)
.value('.','NVARCHAR(MAX)'),1,2,' ') List_Output
FROM @Table1 t
GROUP BY [Case], [Date]