簡體   English   中英

如何提取 MySQL 字符串中的第 n 個單詞並計算單詞出現次數?

[英]How to extract the nth word and count word occurrences in a MySQL string?

我想要一個這樣的mysql查詢:

select <second word in text> word, count(*) from table group by word;

mysql 中的所有正則表達式示例都用於查詢文本是否與表達式匹配,而不是從表達式中提取文本。 有這樣的語法嗎?

以下是針對 OP 的特定問題(提取字符串的第二個單詞)提出的解決方案,但應該注意的是,正如 mc0e 的回答所述,實際上在 MySQL 中不支持開箱即用地提取正則表達式匹配。 如果你真的需要這個,那么你的選擇基本上是 1)在客戶端的后處理中進行,或者 2)安裝一個 MySQL 擴展來支持它。


BenWells 的說法幾乎是正確的。 根據他的代碼,這里有一個稍微調整過的版本:

SUBSTRING(
  sentence,
  LOCATE(' ', sentence) + CHAR_LENGTH(' '),
  LOCATE(' ', sentence,
  ( LOCATE(' ', sentence) + 1 ) - ( LOCATE(' ', sentence) + CHAR_LENGTH(' ') )
)

作為一個工作示例,我使用了:

SELECT SUBSTRING(
  sentence,
  LOCATE(' ', sentence) + CHAR_LENGTH(' '),
  LOCATE(' ', sentence,
  ( LOCATE(' ', sentence) + 1 ) - ( LOCATE(' ', sentence) + CHAR_LENGTH(' ') )
) as string
FROM (SELECT 'THIS IS A TEST' AS sentence) temp

這成功地提取了單詞IS

提取句子中第二個單詞的較短選項:

SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('THIS IS A TEST', ' ',  2), ' ', -1) as FoundText

SUBSTRING_INDEX 的 MySQL 文檔

根據http://dev.mysql.com/ SUBSTRING 函數使用起始位置然后是長度,所以第二個單詞的函數肯定是:

SUBSTRING(sentence,LOCATE(' ',sentence),(LOCATE(' ',LOCATE(' ',sentence))-LOCATE(' ',sentence)))

不,沒有使用正則表達式提取文本的語法。 您必須使用普通的字符串操作函數

或者,從數據庫中選擇整個值(如果您擔心數據傳輸過多,則選擇前 n 個字符),然后在客戶端上使用正則表達式。

正如其他人所說,mysql 不提供用於提取子字符串的正則表達式工具。 這並不是說你不能擁有它們,但如果你准備使用用戶定義的函數來擴展 mysql:

https://github.com/mysqludf/lib_mysqludf_preg

如果您想分發您的軟件,這可能不會有太大幫助,這會成為安裝軟件的障礙,但對於內部解決方案來說,這可能是合適的。

我使用 Brendan Bullen 的回答作為我遇到的類似問題的起點,即檢索 JSON 字符串中特定字段的值。 但是,就像我評論他的回答一樣,這並不完全准確。 如果您的左邊界不僅僅是原始問題中的空格,那么差異就會增加。

更正的解決方案:

SUBSTRING(
    sentence,
    LOCATE(' ', sentence) + 1,
    LOCATE(' ', sentence, (LOCATE(' ', sentence) + 1)) - LOCATE(' ', sentence) - 1
)

兩個區別是 SUBSTRING 索引參數中的 +1 和長度參數中的 -1。

對於“在兩個提供的邊界之間查找字符串的第一次出現”的更通用的解決方案:

SUBSTRING(
    haystack,
    LOCATE('<leftBoundary>', haystack) + CHAR_LENGTH('<leftBoundary>'),
    LOCATE(
        '<rightBoundary>',
        haystack,
        LOCATE('<leftBoundary>', haystack) + CHAR_LENGTH('<leftBoundary>')
    )
    - (LOCATE('<leftBoundary>', haystack) + CHAR_LENGTH('<leftBoundary>'))
)

我不認為這樣的事情是可能的。 您可以使用SUBSTRING函數來提取您想要的部分。

自己開發的正則表達式替換功能可以用於此。

演示

請參閱此 DB-Fiddle 演示,它返回著名十四行詩中的第二個單詞(“I”)及其出現次數(1)。

SQL

假設正在使用 MySQL 8 或更高版本(以允許使用Common Table Expression ),以下將返回第二個單詞及其出現次數:

WITH cte AS (
     SELECT digits.idx,
            SUBSTRING_INDEX(SUBSTRING_INDEX(words, '~', digits.idx + 1), '~', -1) word
     FROM
     (SELECT reg_replace(UPPER(txt),
                         '[^''’a-zA-Z-]+',
                         '~',
                         TRUE,
                         1,
                         0) AS words
      FROM tbl) delimited
     INNER JOIN
     (SELECT @row := @row + 1 as idx FROM 
      (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t1,
      (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t2, 
      (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t3, 
      (SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) t4, 
      (SELECT @row := -1) t5) digits
     ON LENGTH(REPLACE(words, '~' , '')) <= LENGTH(words) - digits.idx)
SELECT c.word,
       subq.occurrences
FROM cte c
LEFT JOIN (
  SELECT word,
         COUNT(*) AS occurrences
  FROM cte
  GROUP BY word
) subq
ON c.word = subq.word
WHERE idx = 1; /* idx is zero-based so 1 here gets the second word */

解釋

上面的 SQL 中使用了一些技巧,並且需要一些認證。 首先,正則表達式替換器用於替換所有連續的非單詞字符塊——每個塊都被單個 tilda ( ~ ) 字符替換。 注意:如果文本中可能出現 tilda,則可以選擇不同的字符。

然后使用此答案中的技術將具有分隔值的字符串轉換為單獨的行值。 它與此答案中的巧妙技術相結合,用於生成由一系列遞增數字組成的表格:在本例中為 0 - 10,000。

該字段的值為:

 "- DE-HEB 20% - DTopTen 1.2%"
SELECT ....
SUBSTRING_INDEX(SUBSTRING_INDEX(DesctosAplicados, 'DE-HEB ',  -1), '-', 1) DE-HEB ,
SUBSTRING_INDEX(SUBSTRING_INDEX(DesctosAplicados, 'DTopTen ',  -1), '-', 1) DTopTen ,

FROM TABLA 

結果是:

  DE-HEB       DTopTEn
    20%          1.2%

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM