2016-04-02 19 views
18

PostgreSQL'de bir dize içindeki bir dize içindeki olay sayısını nasıl sayabilirim?PostgreSQL'de bir dizedeki bir alt dizenin yineleme sayısını sayma


Örnek:

Ben bir tablo var

CREATE TABLE test."user" 
(
    uid integer NOT NULL, 
    name text, 
    result integer, 
    CONSTRAINT pkey PRIMARY KEY (uid) 
) 

result sütunu içerecek şekilde ben bir sorgu yazmak istiyorum nasıl alt dize oname içeren sütun kaç geçişinin. Örneğin, bir satırda hello worldhello world dizesinde iki sütun olduğundan, result sütun 2 içermelidir. result sütunu

enter image description here

ve güncellemek:

enter image description here


I Diğer bir deyişle

, ben girdi olarak alacak bir sorgu yazmaya çalışıyorum regexp_matches işlevinin ve g işlevinin farkında olduğunu bildirir Tam ( g = global) dizenin, alt dizenin tüm yinelemelerinin varlığı için taranması gerekir).

Örnek:

SELECT * FROM regexp_matches('hello world', 'o', 'g'); 

döner

{o} 
{o} 

ve

SELECT COUNT(*) FROM regexp_matches('hello world', 'o', 'g'); 

döner

2 

Ancak, name numaralı sütunun içerdiği alt tabakada kaç tane oluşacağını içerecek şekilde result sütununu güncelleştiren UPDATE sorgusunu nasıl yazacağımı bilmiyorum.

+0

Olası kopyalar (http://stackoverflow.com/questions/25757194/postgresql -sayısı-sayısı-kez-alt--metin-içinde-oluşur) –

cevap

21

ortak bir çözüm, bu mantık dayanır: boş dizgenin yerine ve

(CHAR_LENGTH(name) - CHAR_LENGTH(REPLACE(name, 'substring', ''))) 
/CHAR_LENGTH('substring') 

Dolayısıyla ara dizinin uzunluğu ile eski ve yeni uzunluğu arasındaki fark bölmek :

UPDATE test."user" 
SET result = 
    (CHAR_LENGTH(name) - CHAR_LENGTH(REPLACE(name, 'o', ''))) 
    /CHAR_LENGTH('o'); 
Bunu yapmanın
+0

Bu katı bir cevaptır ve doğru. Benim yazmamla ilgilenebilirsin [bunu yapmanın tüm yöntemleri] (http://dba.stackexchange.com/a/166763/2639) –

+0

Teşekkürler! Herkes biliyor mu, neden daha basit bir yolu yok? Demek istediğim, REPLACE zaten tüm olaylar için tüm dizgeyi taramakta zorluk çeker, neden REPLACE çalışmasının yarısını yapan bir şeye sahip değil - sadece olayları sayın –

+0

@AleksandrLevchuk: Kendi Kullanıcı Tanımlı Fonksiyonunuzu yazabilirsiniz. bu hesaplamayı yaparken https://www.enterprisedb.com/docs/en/9.5/eeguide/EDB_Postgres_Enterprise_Guide.1.041.html adresinde Oracle'ın "REGEXP_COUNT" var. – dnoeth

13

bir Postgres'y yolu bir dizi dize dönüştürür ve dizinin uzunluğunu sayar (ve daha sonra 1 çıkarır):

select array_length(string_to_array(name, 'o'), 1) - 1 

Bunun daha uzun alt dizelerle de çalıştığını unutmayın.

Dolayısıyla:

update test."user" 
    set result = array_length(string_to_array(name, 'o'), 1) - 1; 
+2

Birisi regexp'e ihtiyaç duyarsa, "string_to_array" yerine "regexp_split_to_array" ile bu çözüm de çalışır. –

+0

Bu çözüm, @ dnoeth'in önerisinden büyük ölçüde daha yavaştır. Bence daha fazla Postgres-y değil. İşler farklı bir yöntemle daha hızlı ve daha taşınabilir olduğunda, buna daha iyi * deriz. =) –

+1

@EvanCarroll Maalesef maçın uzunluğunu bilmediğiniz için dnoeth'in cevabı normal ifadelerle çalışmayacaktır. Bu cevap, regex eşleşmeleri ve ham dize eşleşmeleri için çalışacaktır. Bence _better_ dediğimiz şey, yapmaya çalıştığınız her şey için işe yarayan bir çözümdür :) – WebWanderer

0

Diğer bir şekilde:

UPDATE test."user" SET result = length(regexp_replace(name, '[^o]', '', 'g')); 
[PostgreSQL kez substring sayısı numarası metin içerisinde] arasında
İlgili konular