source

MySQL 문자열에서 n번째 단어와 단어 발생 횟수를 추출하는 방법은 무엇입니까?

lovecheck 2023. 2. 1. 21:54
반응형

MySQL 문자열에서 n번째 단어와 단어 발생 횟수를 추출하는 방법은 무엇입니까?

다음과 같은 mysql 쿼리를 원합니다.

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

mysql의 모든 regex 예는 텍스트가 식과 일치하는지 쿼리하는 데 사용되지만 식에서 텍스트를 추출하는 데는 사용되지 않습니다.그런 구문이 있나요?

다음은 OP 고유의 문제(문자열의 두 번째 단어 추출)에 대한 제안 해결책이지만 mc0e의 답변에 따르면 MySQL에서 regex 일치 추출은 지원되지 않습니다.이것이 꼭 필요한 경우 기본적으로 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은 서브스트링을 추출하기 위한 regex 도구를 제공하지 않습니다.그렇다고 해서 사용자 정의 함수를 사용하여 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입니다.

보다 일반적인 솔루션에서는 "제공된2개의 경계 사이에 문자열이 최초로 발생하는 것을 찾습니다."

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

그런 일은 있을 수 없다고 생각해요.하시면 됩니다.SUBSTRING을 사용법

자작 정규 표현 치환 기능을 사용할 수 있습니다.

데모

유명한 소넷의 두 번째 단어("I")와 발생 횟수(1)를 반환하는 DB-Fiddle 데모를 참조하십시오.

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에서는 몇 가지 요령이 사용되고 있으며 인증이 필요합니다.첫째, 정규 표현 리페이서는 연속된 모든 비단어 문자 블록을 단일 틸다로 대체하기 위해 사용됩니다(각 블록은 단일 틸다로 대체됩니다.~)의 문자입니다.주의: 텍스트에 틸다가 나타날 가능성이 있는 경우 다른 문자를 선택할 수 있습니다.

그런 다음 이 답변의 기술을 사용하여 구분된 값을 가진 문자열을 별도의 행 값으로 변환합니다.답변의 영리한 기술과 조합하여 일련의 증가된 숫자로 구성된 표를 만듭니다. 이 경우 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%

언급URL : https://stackoverflow.com/questions/4021507/how-to-extract-the-nth-word-and-count-word-occurrences-in-a-mysql-string

반응형