T-SQL查询:查找最频繁的值对

时间:2019-02-20 23:33:33

标签: sql sql-server tsql

我有一个文本列,其数值用分号分隔。我试图弄清楚如何获得出现在同一行中的最频繁的一对值。我在Python Finding the most frequent occurrences of pairs in a list of lists中找到了一个非常类似的问题的解决方案,但是我不知道如何使用SQL重写它。在下面的示例中,它返回2和3,因为该对在输入集中出现了3次。 :

Input rows      Output
----------      -------
';1;2;3;5'    |  '2;3'     
';2;3'        |  '1;2'
';3;4;5;1;2'  |  '1;3' 
';1;5;2'      |  '1;5'

原始数据:

query result

2 个答案:

答案 0 :(得分:1)

您可以尝试以下方法。首先,使用OPENJSON(),获取所有可能的组合。当OPENJSON解析JSON数组时,JSON文本中元素的索引将作为键(从0开始)返回。然后,用DENSE_RANK()计算最频繁的货币对。

输入:

CREATE TABLE #Items (
   Id int,
   ItemValues varchar(max)
)
INSERT INTO #Items
   (Id, ItemValues)
VALUES   
   (1, '1;2;3;5'),
   (2, '2;3'),
   (3, '3;4;5;1;2'),
   (4, '1;5;2')

声明:

;WITH combinationsCTE AS (
   SELECT 
      CASE 
         WHEN s1.[value] <= s2.[value] THEN CONCAT(s1.[value], ';', s2.[value])
         ELSE CONCAT(s2.[value], ';', s1.[value]) 
      END AS PairValue
   FROM #Items i
   CROSS APPLY (SELECT [key], [value] FROM OPENJSON('["' +  REPLACE(i.ItemValues,';','","') + '"]')) s1
   CROSS APPLY (SELECT [key], [value] FROM OPENJSON('["' +  REPLACE(i.ItemValues,';','","') + '"]')) s2
   WHERE (s1.[key] < s2.[key])
), rankingCTE AS (
   SELECT 
      PairValue, 
      DENSE_RANK() OVER (ORDER BY COUNT(PairValue) DESC) AS PairRank
   FROM combinationsCTE
   GROUP BY PairValue
)
SELECT PairValue
FROM rankingCTE
WHERE PairRank = 1

输出:

PairValue
1;2
1;5
2;3
2;5

答案 1 :(得分:0)

首先具有拆分功能

CREATE FUNCTION Splitfn(@String varchar(8000), @Delimiter char(1))       
returns @temptable TABLE (items varchar(8000))       
as       
begin       
    declare @idx int       
    declare @slice varchar(8000)       

    select @idx = 1       
        if len(@String)<1 or @String is null  return       

    while @idx!= 0       
    begin       
        set @idx = charindex(@Delimiter,@String)       
        if @idx!=0       
            set @slice = left(@String,@idx - 1)       
        else       
            set @slice = @String       

        if(len(@slice)>0)  
            insert into @temptable(Items) values(@slice)       

        set @String = right(@String,len(@String) - @idx)       
        if len(@String) = 0 break       
    end   
return      

end

第二步以单个字符串获取所有行

Declare @val Varchar(MAX); 
Select @val = COALESCE(@val + '; ' + YourColumn, YourColumn) 
        From YourTable

第三步

SELECT TOP 1 items, count(*)
FROM dbo.Splitfn(@Val, ';')
WHERE LTRIM(RTRIM(items)) <> ''
GROUP BY items
ORDER BY Count(*) DESC