web-dev-qa-db-fra.com

Compter le nombre d'occurrences d'une sous-chaîne dans une chaîne dans PostgreSQL

Comment compter le nombre d'occurrences d'une sous-chaîne dans une chaîne dans PostgreSQL?


Exemple:

J'ai une table

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

Je souhaite écrire une requête afin que la variable result contienne le nombre d'occurrences de la sous-chaîne o que la colonne name contient. Par exemple, si dans une ligne, name est hello world, la colonne result doit contenir 2, car il y a deux o dans la chaîne hello world.

En d'autres termes, j'essaie d'écrire une requête qui prendrait en entrée:

 enter image description here

et mettez à jour la colonne result:

 enter image description here


Je connais la fonction regexp_matches et son option g, qui indique que la chaîne complète (g = globale) doit être analysée pour rechercher la présence de toutes les occurrences de la sous-chaîne). 

Exemple:

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

résultats

{o}
{o}

et 

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

résultats

2

Mais je ne vois pas comment écrire une requête UPDATE qui mettrait à jour la colonne result de telle sorte qu'elle contienne le nombre d'occurrences de la sous-chaîne de la colonne name.

26

Une solution commune repose sur cette logique: remplace la chaîne de recherche par une chaîne vide et divise la différence entre ancienne et nouvelle longueur par la longueur de la chaîne de recherche

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

Par conséquent:

UPDATE test."user"
SET result = 
    (CHAR_LENGTH(name) - CHAR_LENGTH(REPLACE(name, 'o', ''))) 
    / CHAR_LENGTH('o');
32
dnoeth

Une manière de faire Postgres'y convertit la chaîne en tableau et compte la longueur du tableau (puis soustrait 1):

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

Notez que cela fonctionne également avec des sous-chaînes plus longues.

Par conséquent:

update test."user"
    set result = array_length(string_to_array(name, 'o'), 1) - 1;
20
Gordon Linoff

Occcurence_Count = LENGTH (REPLACE (string_to_search, string_to_find, '~')) - LENGTH (REPLACE (string_to_search, string_to_find, ''))

Cette solution est un peu plus propre que beaucoup d’autres que j’ai déjà vu, en particulier sans diviseur ..___. Vous pouvez en faire une fonction ou l’utiliser dans une sélection.
Aucune variable requise . J'utilise tilde comme caractère de remplacement, mais tout caractère ne figurant pas dans l'ensemble de données fonctionnera.

0
Robert Bondy

Autre moyen:

UPDATE test."user" SET result = length(regexp_replace(name, '[^o]', '', 'g'));
0
bnson