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

Mysql 是否可以使用分析/窗口函数查找以其他单词开头的单词子集?,mysql,sql,Mysql,Sql,我试图找到一种遍历有序单词列表的单一途径,查找当前单词开头的最短的前一个单词 基本上在以下列表中: 'APP',3 'APPLE',2 'APPLICATION',7 'BOW',2 'BRA',6 'BRAVE',5 'BRAVERY',3 'CANED',2 'CANES',4 我想删除APPLE、APPLICATION、BRAVE和BRAVE,但将它们的数字分数添加到它们开头的词根中,因此APP分数为3+2+7,BRA分数为6+5+3 'APP',12 'BRA',14 'BOW',2

我试图找到一种遍历有序单词列表的单一途径,查找当前单词开头的最短的前一个单词

基本上在以下列表中:

'APP',3
'APPLE',2
'APPLICATION',7
'BOW',2
'BRA',6
'BRAVE',5
'BRAVERY',3
'CANED',2
'CANES',4
我想删除APPLE、APPLICATION、BRAVE和BRAVE,但将它们的数字分数添加到它们开头的词根中,因此APP分数为3+2+7,BRA分数为6+5+3

'APP',12
'BRA',14
'BOW',2
'CANED',2
'CANES',4
虽然勇敢始于勇敢和胸罩,但它的词根是胸罩,因为胸罩比勇敢短

我觉得可以通过创建一个列来完成,每次当前行字不以任何前一行字开头,并且当前行字不长于前一行字时,该列都会递增,然后将其用作分区。。这是我一直坚持的“使用任何前一行单词”的一点——本质上,苹果和应用程序都是从应用程序开始的,但应用程序不是从苹果开始的(勇敢确实是从勇敢开始的),所以将前一行与当前行进行比较是行不通的

我不太在意这是哪一个DB;我使用MySQL 8的分析来实现这一点,但这更像是我所追求的通用技术,因为我可以让我们的sqlserver或oracle轻松完成这项工作


我已经可以使用连接来实现这一点了,我想知道是否有一种方法可以避免所有连接的使用

我意识到这不使用窗口/分析函数,但是如果列表是有序的,这是一个非常简单的问题,只需保持当前前缀字符串,直到列表中的下一个单词与之不匹配(即
名称不象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
prefix  SUM(`Value`)
APP     12
BOW     2
BRA     14
CANED   2
CANES   4
baseword    count
APP    12
BOW     2
BRA    14
CANED   2
CANES   4
然后,该数据可以按前缀进行汇总和分组:

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
输出:

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
prefix  SUM(`Value`)
APP     12
BOW     2
BRA     14
CANED   2
CANES   4
baseword    count
APP    12
BOW     2
BRA    14
CANED   2
CANES   4

(注意我在
胸罩
之前对
进行了自由排序)

使用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

在MySQL中,这可能是解决这个问题的最好方法。@gordonlinoff您在SQLS/Oracle中也会这样做吗?我认为没有一种方法可以欺负分析来解决这个问题吗?@nick对此表示感谢,并指出我在BOW上的排序出现了错误:)@CaiusJard…这是一种不寻常的情况,变量似乎是一个非常好的解决方案。如果您对Oracle中的解决方案感兴趣,请问另一个问题。两个单独的专栏,抱歉没有说清楚