Порахуйте кількість вхідних рядків у полі VARCHAR?


175

У мене така таблиця:

TITLE          |   DESCRIPTION
------------------------------------------------
test1          |   value blah blah value
test2          |   value test
test3          |   test test test
test4          |   valuevaluevaluevaluevalue

Я намагаюся розібратися, як повернути кількість разів, що виникає рядок у кожному з ОПИСУ.

Отже, якщо я хочу порахувати кількість разів, коли з'явиться значення, оператор sql поверне це:

TITLE          |   DESCRIPTION                  |   COUNT
------------------------------------------------------------
test1          |   value blah blah value        |   2
test2          |   value test                   |   1
test3          |   test test test               |   0
test4          |   valuevaluevaluevaluevalue    |   5

Чи можна це зробити? Я взагалі не хочу використовувати php, просто mysql.


4
Відповіді, наведені нижче, вас туди приведуть. Однак не забудьте використовувати CHAR_LENGTH()замість того, LENGTH()якщо ви використовуєте багатобайтові символи.
inhan

На цю тему також відповіли тут
Delickate

Привіт, як мені це зробити із запитом sqlserver?
aintno12u

LENGTH ([поле]) - LENGTH (ЗАМІНА ([поле], '[char_to_find]', ''))
Фенікс

Відповіді:


343

Для цього слід зробити фокус:

SELECT 
    title,
    description,    
    ROUND (   
        (
            LENGTH(description)
            - LENGTH( REPLACE ( description, "value", "") ) 
        ) / LENGTH("value")        
    ) AS count    
FROM <table> 

55
Це рішення - приголомшливе, саме те, що мені було потрібно! Але зауважте, що LENGTH () не є багатобайтовим і ви можете зіткнутися з дивними помилками. Використовуйте замість CHAR_LENGTH () :)
nico gawenda

1
немає різниці у використанні LENGTH()та CHAR_LENGTH()при цьому поділяється на один і той самий підрахунок байт / знаків. @nicogawenda
MohaMad

3
@chyupa undevalueє valueв ньому, тому його слід порахувати. Якщо ви хочете підраховувати лише цілі слова, можливо, вам потрібно буде знайти «значення» або змінити щось складніше, як, наприклад, використовувати регулярний вираз.
PhoneixS

2
Зауважте, що ви шукаєте неправильні підрахунки під час пошуку тексту, у якому також є слова з великими літерами (як німецька, де всі іменники написані з великої літери). ЗАМІНА замінює лише точні збіги. Щоб врахувати всі слова, вам потрібно змінити заміну вище: LENGTH( REPLACE ( LOWER(description), "value", "") )та переконайтесь, що "значення" завжди є нижчим регістром за допомогою PHP strtolower(). PS: Це рішення вище допомогло мені створити свою власну маленьку пошукову систему і зважити результати за кількістю слів у тексті. Дякую!
Кай Ноак

2
ROUNDТут не потрібно. припустимо рядок довжини xіз nвходженнями 'value. LENGTH(description) - LENGTH( REPLACE ( description, "value", "") ) завжди дасть вам n*length("value"), пірнаючи, що за ціною за довжиною завжди залишить цілу кількість n. Не потрібно округляти
Нібріт

21

Трохи простіша та ефективніша версія рішення @yannis:

SELECT 
    title,
    description,    
    CHAR_LENGTH(description) - CHAR_LENGTH( REPLACE ( description, 'value', '1234') ) 
        AS `count`    
FROM <table> 

Різниця полягає в тому, що я замінюю рядок "value" на 1-char коротший рядок ("1234" у цьому випадку). Таким чином, вам не потрібно ділити і округляти, щоб отримати ціле значення.

Узагальнена версія (працює для кожної нитки голки):

SET @needle = 'value';
SELECT 
    description,    
    CHAR_LENGTH(description) - CHAR_LENGTH(REPLACE(description, @needle, SPACE(LENGTH(@needle)-1))) 
        AS `count`    
FROM <table> 

1
+1 для ідеї, хоча я, як правило, віддаю перевагу очевидним реалізаціям, тобто тим, що не потребують додаткових пояснень, навіть якщо вони виглядають менш елегантно.
not2savvy


12

У SQL SERVER така відповідь

Declare @t table(TITLE VARCHAR(100), DESCRIPTION VARCHAR(100))

INSERT INTO @t SELECT 'test1', 'value blah blah value' 
INSERT INTO @t SELECT 'test2','value test' 
INSERT INTO @t SELECT 'test3','test test test' 
INSERT INTO @t SELECT 'test4','valuevaluevaluevaluevalue' 


SELECT TITLE,DESCRIPTION,Count = (LEN(DESCRIPTION) - LEN(REPLACE(DESCRIPTION, 'value', '')))/LEN('value') 

FROM @t

Результат

TITLE   DESCRIPTION               Count
test1   value blah blah value        2
test2   value test                   1
test3   test test test               0
test4   valuevaluevaluevaluevalue    5

У мене немає встановлення MySQL, але я поглянув на пошук еквівалента LEN - LENGTH, а REPLACE - те саме.

Отже, еквівалентний запит у MySql повинен бути

SELECT TITLE,DESCRIPTION, (LENGTH(DESCRIPTION) - LENGTH(REPLACE(DESCRIPTION, 'value', '')))/LENGTH('value') AS Count
FROM <yourTable>

Будь ласка, дайте мені знати, чи працювало воно для вас і в MySql.


3

Ось функція, яка це зробить.

CREATE FUNCTION count_str(haystack TEXT, needle VARCHAR(32))
  RETURNS INTEGER DETERMINISTIC
  BEGIN
    RETURN ROUND((CHAR_LENGTH(haystack) - CHAR_LENGTH(REPLACE(haystack, needle, ""))) / CHAR_LENGTH(needle));
  END;

1
SELECT 
id,
jsondata,    
ROUND (   
    (
        LENGTH(jsondata)
        - LENGTH( REPLACE ( jsondata, "sonal", "") ) 
    ) / LENGTH("sonal")        
)
+
ROUND (   
    (
        LENGTH(jsondata)
        - LENGTH( REPLACE ( jsondata, "khunt", "") ) 
    ) / LENGTH("khunt")        
)
AS count1    FROM test ORDER BY count1 DESC LIMIT 0, 2

Дякую Яннісе, ваше рішення працювало на мене, і тут я ділюсь тим самим рішенням для кількох ключових слів із порядком та лімітом.


1

Це функція mysql з використанням космічної техніки (протестована з mysql 5.0 + 5.5): CREATE FUNCTION count_str( haystack TEXT, needle VARCHAR(32)) RETURNS INTEGER DETERMINISTIC RETURN LENGTH(haystack) - LENGTH( REPLACE ( haystack, needle, space(char_length(needle)-1)) );

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.