T-SQL查询:查找最频繁的值对
我有一个文本列,其中的数值用分号分隔。我试图找出如何获得同一行中出现频率最高的一对值。我在Python中找到了一个非常类似的问题的解决方案,但我不知道如何在下面的示例中使用SQL重写它。它返回2和3,因为这一对在输入集中出现了3次:T-SQL查询:查找最频繁的值对,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个文本列,其中的数值用分号分隔。我试图找出如何获得同一行中出现频率最高的一对值。我在Python中找到了一个非常类似的问题的解决方案,但我不知道如何在下面的示例中使用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'
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'
原始数据:
首先有一个拆分函数
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
第三步
SELECT TOP 1 items, count(*)
FROM dbo.Splitfn(@Val, ';')
WHERE LTRIM(RTRIM(items)) <> ''
GROUP BY items
ORDER BY Count(*) DESC
您可以尝试以下方法。首先,使用OPENJSON获取所有可能的组合。当OPENJSON解析JSON数组时,JSON文本中元素的索引将作为基于0的键返回。然后,计算具有密集_秩的最频繁对 输入:
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
请以文本格式发布数据,而不是图像。此外,你还需要解释940和10662是怎样的预期结果。阅读,你会看到很多原因,为什么这个问题的答案绝对是肯定的!你有一个坏的数据模型,这就是为什么很难使用它。如果要规范化数据库,此任务将非常简单。您的SQL Server版本是什么Developers@AdamStawarek为什么1;2, 1;5和2;5不在输出中?分别为2;3和3;2相同?这可能是在SQL中拆分字符串最糟糕的方法。如果使用2016版或更高版本,最好使用内置字符串分割。对于较低版本,请阅读Aaron Bertrand的《这将返回最频繁的值》,但我的目的是获取最频繁的值对,因此对于每行中的每一组值,我需要找到所有值的组合,并返回在整个集合中最常见的值谢谢,这就是我所需要的
;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