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

时间:2018-08-31 05:59:34

标签: mysql sql

我试图找到一种遍历单词的有序列表的单一方法,寻找当前单词开头的最短的先前单词

基本上在以下列表中:

'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

尽管英勇以勇敢和bra开头,但其词根是bra,因为bra比brave短

我感觉可以做到这一点,方法是创建一列,每当当前行单词不以任何先前的行单词开头并且当前行单词的长度不大于先前的行单词时,该列就递增,然后将其用作我坚持使用的是“带有任何前一行字”位-本质上,Apple和Application均以App开头,但Application并非以Apple开头(而Bravey确实以Brave开头),因此比较立即数像上一行一样无法显示上一行

对于这是哪一个数据库,我并不感到困惑;我正在使用MySQL 8的分析功能,但这是我所追求的通用技术,因为我可以很轻松地让我们的sqlserver或oracle完成工作

我已经可以使用联接来做到这一点,我想知道是否有一种方法可以避免所有使用联接的情况

2 个答案:

答案 0 :(得分:2)

我意识到这不使用窗口/解析函数,但是如果列表是有序的,这是一个很简单的问题,只需维护当前的前缀字符串,直到列表中的下一个单词与之不匹配(即{ 1}},然后将前缀更改为该单词。因此,您可以创建单词及其前缀的列表:

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

SQLFiddle Demo(请注意,我在prefix SUM(`Value`) APP 12 BOW 2 BRA 14 CANED 2 CANES 4 之前对BOW进行了排序)

答案 1 :(得分:1)

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