可以使用分析/窗口函数来查找以其他单词开头的单词子集吗?

gupuwyp2  于 2021-06-20  发布在  Mysql
关注(0)|答案(2)|浏览(267)

我试图找到一种遍历有序单词列表的单通道方法,寻找当前单词开头的最短的前一个单词
基本上在以下列表中:

'APP',3
'APPLE',2
'APPLICATION',7
'BOW',2
'BRA',6
'BRAVE',5
'BRAVERY',3
'CANED',2
'CANES',4

我想去掉apple、application、brave和bravery,但把它们的数字分数加到它们开头的词根上,这样app的分数是3+2+7,bra的分数是6+5+3

'APP',12
'BRA',14
'BOW',2
'CANED',2
'CANES',4

虽然勇敢始于勇敢和胸罩,但它的词根是胸罩,因为胸罩比勇敢短
我觉得可以通过创建一个列来实现,每次当前行单词不以任何前一行单词开头,并且当前行单词不长于前一行单词时,该列都会递增,然后将其用作分区。。这是“与任何前一行字”位,我坚持-本质上是苹果和应用程序都始于应用程序,但应用程序并不始于苹果(和勇敢的开始与勇敢),所以比较前一行是像目前的行不起作用
我并不担心这是哪个数据库;我使用MySQL8的分析来实现这一点,但这更像是我所追求的一般技术,因为我可以让我们的sqlserver或oracle轻松地完成这项工作
我已经可以使用连接来实现这一点了,我想知道是否有一种方法可以避免所有连接的使用

k10s72fa

k10s72fa1#

使用cte的替代版本。还包括创建插入,以便您可以剪切和粘贴作为完整示例。

declare @w table(word varchar(20), cnt int)
insert @w values ('APP',3)
,('APPLE',2)
,('APPLICATION',7)
,('BRA',6)
,('BRAVE',5)
,('BRAVERY',3)
,('BOW',2)
,('CANES',4)
,('CANED',2)

;with cte as(
    select w.word, w2.word as baseword, w.cnt
    from @w w
    join @w w2 on w.word like w2.word+'%' 
    and not exists(select * from @w w3 where w.word like w3.word+'%' and len(w3.word)<len(w2.word))
)
select baseword, sum(cnt) as [count] from cte group by baseword

输出:

baseword    count
APP    12
BOW     2
BRA    14
CANED   2
CANES   4
uhry853o

uhry853o2#

我意识到这不使用窗口/分析函数,但如果列表是有序的,这是一个相当容易的问题,只要保持当前前缀字符串,直到列表中的下一个单词不匹配它(即。 Name NOT LIKE CONCAT(@prefix, '_%') ,然后将前缀改为该单词。因此,您可以创建单词及其前缀的列表:

SELECT Name, Value, @prefix:=IF(Name NOT LIKE CONCAT(@prefix, '_%'), Name, @prefix) AS prefix
FROM table1
JOIN (SELECT @prefix := '~') p;

输出:

Name            Value   prefix
APP             3       APP
APPLE           2       APP
APPLICATION     7       APP
BOW             2       BOW
BRA             6       BRA
BRAVE           5       BRA
BRAVERY         3       BRA
CANES           4       CANES
CANED           2       CANED

然后,这些数据可以按前缀进行求和和和分组:

SELECT prefix, SUM(`Value`)
FROM (SELECT Name, Value, @prefix:=IF(Name NOT LIKE CONCAT(@prefix, '_%'), Name, @prefix) AS prefix
      FROM table1
      JOIN (SELECT @prefix := '~') p
      ) t2
GROUP BY prefix

输出:

prefix  SUM(`Value`)
APP     12
BOW     2
BRA     14
CANED   2
CANES   4

sqlfiddle演示(注意我随意排序 BOW 之前 BRA )

相关问题