不是重复的:我另一个标题相同的问题针对MySQL,这个针对oracle
我试图找到一种遍历单词的有序列表的单一方法,寻找当前单词开头的最短的先前单词
基本上在以下列表中(2列,varchar,int):
'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短于勇敢
我感觉可以做到这一点,方法是创建一列,每当当前行单词不以任何先前的行单词开头并且当前行单词的长度不大于先前的行单词时,该列就递增,然后将其用作我坚持使用的是“带有任何前一行字”位-本质上,Apple和Application均以App开头,但Application并非以Apple开头(而Bravey确实以Brave开头),因此比较立即数像上一行一样无法显示上一行
我已经可以使用MySQL和SQLS中的联接和变量,以及在Oracle中进行联接(将表自身返回几次)来完成此操作。我想知道是否有一种有效的方法可以避免所有联接的使用
答案 0 :(得分:1)
在Oracle中,您可以使用MATCH_RECOGNIZE
子句轻松解决此问题。问题是MATCH_RECOGNIZE
需要Oracle 12.1或更高版本。
MATCH_RECOGNIZE
具有分析功能的某些功能,但添加了一些其他功能。在以下解决方案中,关键部分是能够一次性将行标记为“根”(我将其命名为r
)或“扩展”(e
),同时能够-在同一遍中-识别出一个“组”(在技术上是一个 match )的结束处,然后是下一个组的开始-并仍在同一遍中对每个匹配的值求和。< / p>
我不认为仅使用分析功能就可以轻松完成同样的事情。
注意:对于Oracle的较旧版本,可以使用MODEL
子句(也是Oracle专有的)解决该问题。这需要Oracle 10.1或更高版本。解决方案位于此答案的底部(在MATCH_RECOGNIZE
解决方案之后)。
with
simulated_data(word, val) as (
select 'APP' , 3 from dual union all
select 'APPLE' , 2 from dual union all
select 'APPLICATION', 7 from dual union all
select 'BOW' , 2 from dual union all
select 'BRA' , 6 from dual union all
select 'BRAVE' , 5 from dual union all
select 'BRAVERY' , 3 from dual union all
select 'CANED' , 2 from dual union all
select 'CANES' , 4 from dual
)
select root_word, total_value
from simulated_data
match_recognize(
order by word
measures r.word as root_word,
sum(val) as total_value
pattern ( r e* )
define e as e.word like r.word || '%'
)
;
ROOT_WORD TOTAL_VALUE
----------- -----------
APP 12
BOW 2
BRA 14
CANED 2
CANES 4
使用MODEL
子句的解决方案:
with
simulated_data(word, val) as (
select 'APP' , 3 from dual union all
select 'APPLE' , 2 from dual union all
select 'APPLICATION', 7 from dual union all
select 'BOW' , 2 from dual union all
select 'BRA' , 6 from dual union all
select 'BRAVE' , 5 from dual union all
select 'BRAVERY' , 3 from dual union all
select 'CANED' , 2 from dual union all
select 'CANES' , 4 from dual
)
select rw as root_word, tv as total_value
from (
select rw, tv, fl
from simulated_data
model
dimension by (row_number() over (order by word) as rn)
measures (word, val, rpad('x', 4000, 'x') as rw, 0 as tv, 0 as fl)
rules (
rw[any] = case instr(word[cv()], rw[cv()-1])
when 1 then rw[cv()-1] else word[cv()] end,
tv[any] = case rw[cv()] when rw[cv()-1]
then tv[cv()-1] + val[cv()] else val[cv()] end,
fl[any] = case rw[cv()] when rw[cv()+1]
then 0 else 1 end
)
)
where fl = 1
;
答案 1 :(得分:0)
您可以尝试在CASE WEHN
中用LIKE
编写一个GROUP BY
查询1 :
SELECT
(CASE
WHEN name LIKE 'APP%' THEN 'APP'
WHEN name LIKE 'BRA%' THEN 'BRA'
ELSE name
END) name,SUM(amount)
FROM T
GROUP BY
CASE
WHEN name LIKE 'APP%' THEN 'APP'
WHEN name LIKE 'BRA%' THEN 'BRA'
ELSE name
END
如果您不想将CASE WEHN
中的LIKE
与GROUP BY
一起使用。
我将为您的关键字名称创建一个mapper
表,因为您需要告诉程序哪个是您的期望关键字。
CREATE TABLE T(name varchar(50),amount int);
insert into t values ('APP',3);
insert into t values ('APPLE',2);
insert into t values ('APPLICATION',7);
insert into t values ('BOW',2);
insert into t values ('BRA',6);
insert into t values ('BRAVE',5);
insert into t values ('BRAVERY',3);
insert into t values ('CANED',2);
insert into t values ('CANES',4);
CREATE TABLE maaper(
name VARCHAR(50)
);
INSERT INTO maaper VALUES ('APP');
INSERT INTO maaper VALUES ('BRA');
查询1 :
SELECT coalesce(t2.name,t1.name) name,sum(AMOUNT)
FROM T t1 LEFT JOIN (
SELECT name
FROM maaper
) t2 ON t1.name like t2.name || '%'
group by coalesce(t2.name,t1.name)
Results :
| NAME | SUM(AMOUNT) |
|-------|-------------|
| BRA | 14 |
| CANED | 2 |
| APP | 12 |
| CANES | 4 |
| BOW | 2 |