如何从SQL中的给定结果字符串中找到最大组合

时间:2018-01-09 18:33:08

标签: sql sql-server

这是输出。

ID     Stack    
-----------------------------------
123    307290,303665,307285  
123    307290,307285,303424,303665  
123    307290,307285,303800,303665  
123    307061,307290  

我想要输出只有最后三行。原因是在第一个输出线堆栈列中,所有三个数字在输出行2和3堆栈列中都可用,因此我不需要输出行1.

但是输出行2,3,4是不同的所以我想在结果中使用这些行。

我尝试使用row_number()charindex,但我没有得到正确的结果。

谢谢。

1 个答案:

答案 0 :(得分:0)

所有评论都告诉您更改数据库的结构是正确的!你真的应该避免使用逗号分隔值。这打破1.NF,永远是痛苦的。

第二个CTE的结果可能用于将所有数据转换为新的1:n相关结构。

这样的东西?

DECLARE @tbl TABLE(ID INT,Stack VARCHAR(100));
INSERT INTO @tbl VALUES
 (123,'307290,303665,307285')
,(123,'307290,307285,303424,303665')
,(123,'307290,307285,303800,303665')
,(123,'307061,307290');

WITH Splitted AS
(
    SELECT ID
          ,Stack
          ,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RowIndex
          ,CAST('<x>' + REPLACE(Stack,',','</x><x>') + '</x>' AS XML) Casted 
    FROM @tbl
)
,DerivedDistinctValues AS
(
    SELECT DISTINCT 
           ID
          ,Stack
          ,RowIndex
          ,StackNr.value('.','int') AS Nr
    FROM Splitted
    CROSS APPLY Casted.nodes('/x') AS A(StackNr)
)
SELECT ddv1.ID
      ,ddv1.Stack
FROM DerivedDistinctValues AS ddv1
FULL OUTER JOIN DerivedDistinctValues AS ddv2 ON ddv1.RowIndex<>ddv2.RowIndex
                                             AND ddv1.Nr=ddv2.Nr
WHERE ddv2.ID IS NULL
GROUP BY ddv1.ID,ddv1.Stack 

这将很慢,特别是对于较大的数据集。

一些解释:

第一个CTE会将CSV编号转换为<x>307290</x><x>303665</x>...这可以转换为XML,这允许生成一个派生表,将所有数字作为行返回。这发生在调用XQuery函数.nodes()的第二个CTE中。

最后一个查询将执行完全外部连接 - 每个连接都有一个。将保留所有行,其中至少有一行没有相应的行。

但我认为,这可能不适用于每种情况(例如循环数据)