如何在Oracle中通过列字符串创建词云

rqenqsqc  于 2022-11-03  发布在  Oracle
关注(0)|答案(2)|浏览(137)

我试图找到一些文章,帮助我的工作,我必须做的。我有一个表的问题和答案的客户服务在一个网站上,我想创建之间的因果关系,无论投诉和问题的答案,我们的想法是使用一个直方图,您可以为客户在STR_COMPLAINTS列中的投诉中使用最多的词语以及在STR_COMPLAINTS处理中使用最多的词语指明方向在答案列中输入ANSWERS。如下例所示:
| 识别码|STR_投诉|字符串_答案|
| - -|- -|- -|
| 一个|我的披萨冷了|我们将在上比萨饼之前创建温度控制|
| :-----------------------|- ---------------------------------|- ---------------------------|
| 2个|我的汉堡都凉了|我们会在上汉堡前设置温度控制|

预期成果:

| 字|问题|答案|
| - -|- -|- -|
| 我的|2个|第0页|
| 比萨饼|2个|2个|
| 来了|2个|第0页|
| 冷的|2个|第0页|
| 我们|第0页|2个|
| 遗嘱|第0页|2个|
| 创造了|第0页|2个|
| 一种|第0页|2个|
| 温度,温度|第0页|2个|
| 控制器|第0页|2个|
| 之前|第0页|2个|
| 上菜|第0页|2个|
| 的|第0页|2个|
| 汉堡包|2个|2个|

sg3maiej

sg3maiej1#

你可以标记每一个抱怨和每一个答案来得到所有的单个单词,从中得到所有的唯一单词,然后计数每个单词出现了多少次。
这种方法使用正则表达式对字符串进行标记化,这可能很慢而且开销很大,但是您可以根据需要修改该部分。
每一列都在它自己的递归CTE中处理,然后第三个CTE获得唯一的单词。第三个CTE,以及单词列表,然后与前两个CTE进行外部连接,并计算匹配的ID。(如果不想多次计算重复的单词,您 * 可能 * 想计算非重复的ID。)

with q (id, str_complaints, pos, word) as (
  select id, str_complaints, 1, regexp_substr(str_complaints, '(\w+)', 1, 1, null, 1)
  from complaints
  union all
  select id, str_complaints, pos + 1, regexp_substr(str_complaints, '(\w+)', 1, pos + 1, null, 1)
  from q
  where regexp_substr(str_complaints, '(\w+)', 1, pos + 1, null, 1) is not null
),
a (id, str_answers, pos, word) as (
  select id, str_answers, 1, regexp_substr(str_answers, '(\w+)', 1, 1, null, 1)
  from complaints
  union all
  select id, str_answers, pos + 1, regexp_substr(str_answers, '(\w+)', 1, pos + 1, null, 1)
  from a
  where regexp_substr(str_answers, '(\w+)', 1, pos + 1, null, 1) is not null
),
w (word) as (
  select word
  from q
  union
  select word
  from a
)
select w.word, count(q.id) as question, count(a.id) as answers
from w
left join q on q.word = w.word
left join a on a.word = w.word
group by w.word

| 字|问题|答案|
| - -|- -|- -|
| 创造了|第0页|2个|
| 之前|第0页|2个|
| 控制器|第0页|2个|
| 温度,温度|第0页|2个|
| 的|第0页|2个|
| 冷的|2个|第0页|
| 一种|第0页|2个|
| 比萨饼|一个|一个|
| 我的|2个|第0页|
| 来了|2个|第0页|
| 我们|第0页|2个|
| 遗嘱|第0页|2个|
| 汉堡包|一个|一个|
| 上菜|第0页|2个|
fiddle,其示出了一些中间数据。

hs1ihplo

hs1ihplo2#

如果你没有/知道/想要regexp -你可以使用用户定义的函数,我用它来分割csv或任何其他文本。函数使用sql建模,可以通过分隔符分割任何字符串,分隔符也可以是空格(“”)。所以,它可以分割单词。返回类型也是用户定义的。

create or replace TYPE STRING_ARRAY AS VARRAY(4000) OF VARCHAR2(1000);
--  ------------------------------------------------------------------
--
create or replace 
    FUNCTION split ( csvString  IN  VarChar2, delimiter  IN  VarChar2 := ',') RETURN STRING_ARRAY 
        AS 
    BEGIN
        Declare
            elements     STRING_ARRAY := STRING_ARRAY();
            CURSOR c IS
                SELECT  COL1
                FROM    (   SELECT INDX, MY_STR1, COL1_ELEMENTS, COL1
                            FROM
                                (   SELECT 0 "INDX", COL1 "MY_STR1", COL1_ELEMENTS, COL1
                                    FROM
                                        (
                                            SELECT
                                                REPLACE(COL1, delimiter || ' ', delimiter) "COL1",  
                                                Trim(Length(Replace(COL1, delimiter || ' ', delimiter))) - Trim(Length(Translate(REPLACE(COL1, delimiter || ' ', delimiter), 'A' || delimiter, 'A'))) + 1 "COL1_ELEMENTS"
                                            FROM 
                                                (SELECT csvString "COL1" FROM DUAL)     
                                        )
                                )
                            MODEL       
                                DIMENSION BY(0 as INDX)
                                MEASURES(COL1, COL1_ELEMENTS, CAST('a' as VarChar2(4000)) as MY_STR1)
                                RULES ITERATE (1000)        -- If you don't know the number of elements this should be bigger then you aproximation. Othewrwise it will split given number of elements
                                (
                                    COL1_ELEMENTS[ITERATION_NUMBER + 1] = COL1_ELEMENTS[0],
                                    MY_STR1[0] = COL1[CV()],
                                    MY_STR1[ITERATION_NUMBER + 1] = SubStr(MY_STR1[ITERATION_NUMBER], InStr(MY_STR1[ITERATION_NUMBER], delimiter, 1) + Length(delimiter)),
                                    COL1[ITERATION_NUMBER + 1] = SubStr(MY_STR1[ITERATION_NUMBER], 1, CASE WHEN InStr(MY_STR1[ITERATION_NUMBER], delimiter) <> 0 THEN InStr(MY_STR1[ITERATION_NUMBER], delimiter)-1 ELSE Length(MY_STR1[ITERATION_NUMBER]) END)
                                )
                        )
                WHERE INDX > 0 And INDX <= COL1_ELEMENTS; 
            --
            cStr    VarChar2(1000);
            i       Number := 1;
        Begin 
            If c%ISOPEN Then 
                CLOSE c; 
            End If;
            OPEN c;
            LOOP
                FETCH c Into cStr;
                EXIT WHEN c%NOTFOUND;
                elements.extend;
                elements(i) := cStr;
                i := i + 1;
            END LOOP;
            CLOSE c;
            RETURN elements;
        End;
    END split;
--
--  ------------------------------------------------------------------

使用您的示例数据:

WITH
    a_tbl AS
        (
            Select  1 "ID", 'My pizza  came cold' "Q_STR", 'We will create a temperature control before serving the pizza' "A_STR"  From Dual Union All
            Select  2 "ID", 'My Burger came cold' "Q_STR", 'We will create a temperature control before serving the Burger' "A_STR" From Dual
        ),

......你可以收集问题和答案中的所有单词--使用split()函数创建一个cte(我将其命名为all_words),如下所示:

all_words AS
        (
            Select  q.ID "ID", Replace(Replace(Replace(Replace(w.COLUMN_VALUE, ',', ''), '.', ''), '!', ''), '?', '') "Q_WORD", Null "A_WORD"
            From a_tbl q
            Inner Join TABLE(SPLIT(Q_STR, ' ')) w ON (1 = 1)
          Union All
            Select  a.ID "ID", Null "Q_WORD", Replace(Replace(Replace(Replace(w.COLUMN_VALUE, ',', ''), '.', ''), '!', ''), '?', '') "A_WORD"
            From a_tbl a
            Inner Join TABLE(SPLIT(a.A_STR, ' ')) w ON (1 = 1)
        )

主sql:

Select 
    COALESCE(Q_WORD, A_WORD) "WORD",
    Count(Q_WORD)  "QUESTION",
    Count(A_WORD)  "ANSWER"
From all_words
Group By COALESCE(Q_WORD, A_WORD)
Order By Count(Q_WORD) DESC

结果应该是:
| 字|问题|答案|
| - -|- -|- -|
| 我的|2个|第0页|
| 冷的|2个|第0页|
| 来了|2个|第0页|
| 汉堡包|一个|一个|
| 比萨饼|一个|一个|
| 上菜|第0页|2个|
| 我们|第0页|2个|
| 遗嘱|第0页|2个|
| 的|第0页|2个|
| 温度,温度|第0页|2个|
| 控制器|第0页|2个|
| 之前|第0页|2个|
| 创造了|第0页|2个|
| 一种|第0页|2个|
此致。
“附言”
你应该考虑在计数前把所有的单词都小写/大写,因为单词“My”和“my”将被分开计数,因为一个在句子的开头,另一个不在。

相关问题