VARCHAR alanındaki bir dizenin yineleme sayısını say?


175

Ben böyle bir tablo var:

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

Nasıl bir dize her biri bir dize oluşur sayısını döndürmek için anlamaya çalışıyorum.

Yani, 'değer' görüntülenme sayısını saymak istiyorsanız, sql deyimi bu döndürür:

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

Bunu yapmanın bir yolu var mı? Ben hiç php kullanmak istemiyorum, sadece mysql.


4
Aşağıdaki yanıtlar sizi oraya götürecektir. Ancak, çok baytlı karakterler kullanmak CHAR_LENGTH()yerine kullanmayı unutmayın LENGTH().
inhan

Bu konuya da burada
Delickate

Merhaba, bunu sqlserver sorgusu ile nasıl yapabilirim?
aintno12u

UZUNLUK ([alan]) - UZUNLUK (DEĞİŞTİR ([alan], '[char_to_find]', ''))
Phoenix

Yanıtlar:


343

Bu hile yapmalı:

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

55
Bu çözüm müthiş, tam ihtiyacım olan şey! Ancak, LENGTH () öğesinin çok baytlık güvenli olmadığını ve garip hatalarla karşılaşabileceğinizi unutmayın. Bunun yerine CHAR_LENGTH () kullanın :)
nico gawenda

1
aynı sayım byte / char değerinin kullanımı LENGTH()ve CHAR_LENGTH()bölünmesi arasında bir fark yoktur . @nicogawenda
MohaMad

3
@chyupa undevaluevar value, bu yüzden sayılmalıdır. Yalnızca tam kelimeleri saymak istiyorsanız, belki de 'değer' aramanız veya normal ifadeyi kullanmak gibi daha karmaşık bir şeyle betimlemeniz gerekir.
PhoneixS

2
Büyük harflerle de kelimeleri olan metinlerde (tüm isimlerin büyük harfle yazıldığı Almanca gibi) arama yaparken yanlış sayım yaptığınızı unutmayın. REPLACE yalnızca tam eşleşmelerin yerini alır. Tüm kelimeleri dikkate almak için yukarıdaki değiştirmeyi şu şekilde değiştirmeniz gerekir: LENGTH( REPLACE ( LOWER(description), "value", "") )ve PHP kullanarak "değer" in her zaman küçük harf olduğundan emin olun strtolower(). Not: Yukarıdaki bu çözüm, kendi küçük arama motorumu oluşturmama ve sonuçları metin içindeki kelime sayısına göre ağırlıklandırmama yardımcı oldu. Teşekkürler!
Kai Noack

2
ROUNDBurada gereksizdir. uzunlukta bir dize varsayalım xile ngerçekleşme 'value. LENGTH(description) - LENGTH( REPLACE ( description, "value", "") ) size her zaman verecek n*length("value"), dalışla değer uzunluğuna her zaman tam bir sayı bırakacaktır n.
Yuvarlanmaya

21

@Yannis çözümünün biraz daha basit ve daha etkili varyasyonu:

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

Aradaki fark, "değer" dizesini 1 karakterlik kısa bir dizeyle (bu durumda "1234") değiştirmem. Bu şekilde bir tamsayı değeri elde etmek için bölmeniz ve yuvarlamanız gerekmez.

Genelleştirilmiş sürüm (her iğne dizisi için çalışır):

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

1
Fikir için +1, ancak genellikle belirgin uygulamaları tercih ederim, yani daha az zarif görünseler bile ek açıklama gerektirmez.
not2savvy

19

bunu dene:

 select TITLE,
        (length(DESCRIPTION )-length(replace(DESCRIPTION ,'value','')))/5 as COUNT 
  FROM <table> 


SQL Keman Demosu


2
uzunluk ikili güvenli değil, char_length () kullanın
luky

12

SQL SUNUCU, bu cevap

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

Sonuç

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

MySQL yüklemem yok, ancak REPLACE aynı iken LEN Eşdeğeri LENGTH .

Yani MySql'deki eşdeğer sorgu

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

MySql'de sizin için de işe yarayıp yaramadığını lütfen bize bildirin.


3

İşte bunu yapacak bir işlev.

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

Teşekkürler Yannis, çözümünüz benim için çalıştı ve burada sipariş ve limit ile birden fazla anahtar kelime için aynı çözümü paylaşıyorum.


1

Bu, uzay tekniğini kullanan mysql işlevidir (mysql 5.0 + 5.5 ile test edilmiştir): CREATE FUNCTION count_str( haystack TEXT, needle VARCHAR(32)) RETURNS INTEGER DETERMINISTIC RETURN LENGTH(haystack) - LENGTH( REPLACE ( haystack, needle, space(char_length(needle)-1)) );

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.