Sql 在列中绘制为字符串-仅当两个后续字符串是唯一的时

Sql 在列中绘制为字符串-仅当两个后续字符串是唯一的时,sql,sql-server,tsql,Sql,Sql Server,Tsql,如何修改下面的代码,使最终的集群字符串只包含错误代码,而错误代码与前一个字符串不重复,因此对于第3行,只返回一个C(跳过第二个C),对于第1行,则返回A、C、A、B(由于相邻的重复,跳过第二个A) 您刚刚错过了内部不同的: SELECT DISTINCT ', ' + ErrorCode FROM @table1 t1 WHERE t1.[Case] = tabel2.[Case] AND t1.[Date] = ta

如何修改下面的代码,使最终的集群字符串只包含错误代码,而错误代码与前一个字符串不重复,因此对于第3行,只返回一个C(跳过第二个C),对于第1行,则返回A、C、A、B(由于相邻的重复,跳过第二个A)


您刚刚错过了
内部
不同的

SELECT DISTINCT ', ' + ErrorCode
           FROM @table1 t1
           WHERE t1.[Case] = tabel2.[Case]
                 AND t1.[Date] = tabel2.[Date]
           FOR XML PATH('')

您可以尝试以下查询

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]
你可以找到现场演示

要仅获取唯一值,需要使用
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]
我就是这样做的

首先,您最好在表中有一个唯一标识每一行的主键或唯一约束,即集合论-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       |

正如我在你的文章中告诉你的,没有邻居数据这样的东西。例如,
2018-01-15
上案例1的所有值(在提供的示例中为ACAAB)没有隐式排序顺序。。。使用ACAAB时,同一查询可能会返回100次,但突然您会得到
AAABC
,或
BAACA
,或任何其他组合。。。简而言之:对于给定的数据,这是不可能的。如果插入了排序列(如附加的
IDENTITY
值),则可以阅读
LAG()
LEAD()
。请不要使用
varchar
存储日期。使用
日期
日期时间2(0)
或其他日期类型。。
varchar(20)
比任何日期类型占用更多空间,并且不能保证内容有效。没有任何东西可以阻止某人插入
2018-24-01
此外,
相邻的
以什么顺序插入?除非指定顺序,否则结果将以随机顺序返回,无论对服务器来说是什么样的顺序。除非明确指定订单,否则第一行很容易包含
ACABA
ABACA
AAABC
。并行查询处理将以随机顺序返回结果。如何判断第二行是早于第四行还是晚于第四行(两者的日期相同).我所说的顺序:顺序是由正在处理的行的方向定义的:从上面的行到下面的行,所以例如2018-01-15:A C A B和我想保持相同的顺序,但只是消除第二个A:A C A B。OP发布了A,我提供了完全相同的解决方案。但在这种情况下,OP不希望得到一个不同的列表,而只是减少邻接兄弟。在投入更多时间之前,您可能需要阅读我的评论;-)这似乎不符合OP的要求。您的第一个查询将生成OP正在获取的相同内容,而您的第二个查询将删除所有重复,而不仅仅是重复相邻的重复。
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       |