【问题标题】:Most frequent combination of words/characters SQL Server最常见的单词/字符组合 SQL Server
【发布时间】:2018-04-01 19:33:14
【问题描述】:

我正在分析“RawDataDescriptions”表中的数据,该表中的“描述”字段是开放式供用户输入的。

我正在寻找方法,通过短语或经常出现的字符串(包括它们出现的次数)对描述进行广泛分类。

我没有特定的单词或短语要寻找我可以使用“like”语句的地方,而是寻找字段之间的共性。

在通过其他问题寻找这一点的同时,我设法找到了一个查询,该查询针对我自己的表进行了调整,该表得到了最常见的单词(粘贴在下面),但当然,仅一个单词就几乎没有 - 如果有的话 - 洞察力描述。

是否可以进行查询以提供短语计数而不仅仅是单个单词?如果是这样,它的主要组成部分是什么?

WITH E1(N) AS 
(
    SELECT 1 
    FROM (VALUES
        (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
    ) t(N)
),
E2(N) AS (SELECT 1 FROM E1 a CROSS JOIN E1 b),
E4(N) AS (SELECT 1 FROM E2 a CROSS JOIN E2 b)
SELECT
    x.Item,
    COUNT(*)
FROM RawDataDescriptions p
CROSS APPLY (
SELECT 
        ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
        Item       = LTRIM(RTRIM(SUBSTRING(p.[Description], l.N1, l.L1)))
        FROM (
            SELECT s.N1,
                L1 = ISNULL(NULLIF(CHARINDEX(' ',p.[Description],s.N1),0)-
s.N1,4000)
            FROM(
                SELECT 1 UNION ALL
                SELECT t.N+1 
                FROM(
                    SELECT TOP (ISNULL(DATALENGTH(p.[Description])/2,0))
                        ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
                    FROM E4
                ) t(N)
                WHERE SUBSTRING(p.[Description] ,t.N,1) = ' '
            ) s(N1)
        ) l(N1, L1)
) x
WHERE x.item <> ''
GROUP BY x.Item
ORDER BY COUNT(*) DESC

*编辑 - 不可行。替代的期望结果:

示例表

Id | Description  
---+--------------------------
01 | Customer didn't like it  
02 | Person liked it  
03 | Person didn't like it  
04 | Client didn't like it  
05 | person liked it   

@Parameter = 3

想要的结果:

string           | count  
-----------------+-------
didn't like it   | 3  
Person liked it  | 2  

编辑 2** 原来的问题是可行的 - 查看答案

【问题讨论】:

  • 我认为你做不到。可以为单个单词做它,因为很清楚单词是什么。但是定义一个短语....它可以是两个词,三个或十个。您必须逐行解析多个单词的所有可能组合。对于仅包含几个单词的条目而言,这实际上可能有数千种可能性。
  • 如果我做了一些与 OP 中的查询类似的事情,但只使用 3 个单词而不是一个单词呢?
  • 你可以这样做。您将拥有 NumberOfWords - 2 作为每行可能的短语数。
  • 如何编码来调整字数?
  • 你不能仅仅修改这个来做到这一点。您发布的代码使用空格作为分隔符将字符串解析为行。你必须从头开始,把你的价值观变成三个词组。您还需要决定如何处理只有一两个单词的短语。你用这些做什么?

标签: sql sql-server tsql


【解决方案1】:

这是一种选择。我有几个问题,例如标点符号、控制字符,尤其是大型表格的性能

示例

Declare @RawDataDescriptions Table ([Id] varchar(50),[Description] varchar(50))
Insert Into @RawDataDescriptions Values 
 ('01','Customer didn''t like it')
,('02','Person liked it')
,('03','Person didn''t like it')
,('04','Client didn''t like it')
,('05','person liked it')

;with cte as (
    Select Id
          ,B.* 
      From  @RawDataDescriptions A
      Cross Apply (
                    Select RetSeq = Row_Number() over (Order By (Select null))
                          ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
                    From  (Select x = Cast('<x>' + replace((Select replace(A.[Description],' ','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
                    Cross Apply x.nodes('x') AS B(i)
                  ) B 
)
Select Phrase
      ,Cnt  = count(*)
 From  cte A
 Cross Apply (
     Select Phrase = stuff((Select ' '+RetVal
                            From  cte 
                            Where ID = A.ID
                              and RetSeq between A.RetSeq and A.RetSeq+2
                            Order By RetSeq
                            For XML Path('')),1,1,'')

             ) B
  Where Phrase like '% % %'
  Group By Phrase
  Having count(*)>1
  Order By 2 Desc

退货

Phrase           Cnt
didn't like it   3
Person liked it  2

更新 - TVF - 更好的性能

我决定我可能想把它变成一个表值函数,并且对性能提升感到震惊。例如,我有来自 FRED(美联储经济数据)的 130,000 条描述,并且能够在 9 秒内生成常用短语(n 个单词)的列表。

用法

Select Phrase = B.RetVal
      ,Cnt    = count(*)
 From YourTable A
 Cross Apply [dbo].[tvf-Str-Parse-Phrase](A.YourColumn,' ',4) B
 Group By B.RetVal
 Having count(*)>1
 Order By 2 Desc

有兴趣的 TVF

CREATE FUNCTION [dbo].[tvf-Str-Parse-Phrase] (@String varchar(max),@Delimeter varchar(25),@WordCnt int)
Returns Table 
As
Return (  
 with cte as (
      Select RetSeq = Row_Number() over (Order By (Select null))
            ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)')))
      From  (Select x = Cast('<x>' + replace((Select replace(@String,@Delimeter,'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
      Cross Apply x.nodes('x') AS B(i)
)
Select RetSeq = Row_Number() over (Order By (Select Null))
      ,B.RetVal
 From  cte A
 Cross Apply (Select RetVal = stuff((Select ' '+RetVal From cte Where RetSeq between A.RetSeq and A.RetSeq+@WordCnt-1 For XML Path('')),1,1,'') ) B
 Where B.RetVal like Replicate('% ',@WordCnt-1)+'%'
);
--Select * from [dbo].[tvf-Str-Parse-Phrase]('This is some text that I want parsed',' ',4)

【讨论】:

  • 这很漂亮约翰。我挣扎了一会儿(愚蠢的区分大小写的排序规则)。但效果很好。我什至稍微调整它以接收长度参数并且效果很好。我刚刚调整了 Where 子句以使用复制。
  • @SeanLange 如果有兴趣,我将其转换为 TVF。性能提升令人震惊。见编辑/更新
  • @SaleemKhan 很高兴它有帮助
【解决方案2】:

您可以在桌子上启用Microsoft Full Text Index 并在桌子上执行此类查找常用词和字符分析。

【讨论】:

    猜你喜欢
    • 2014-12-14
    • 2014-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多