Comment concaténer des colonnes dans un Postgres SELECT?

145

J'ai deux colonnes de chaîne aet bdans une table foo.

select a, b from foorenvoie les valeurs aet b. Cependant, la concaténation de aet bne fonctionne pas. J'ai essayé :

select a || b from foo

et

select  a||', '||b from foo

Mise à jour à partir des commentaires: les deux colonnes sont de type character(2).

Alex
la source
... ou d'un autre texttype?
PM 77-1
@acfrancis Puisque OP dit que concatenateje doute qu'il ait affaire à des types numériques, bien que PostgreSQL se charge également de certains d'entre eux. Voir ici: postgresql.org/docs/9.1/static/functions-string.html
PM 77-1
Oui, ces colonnes sont du caractère (2). "+" ne fonctionne pas - "Aucun opérateur ne correspond au nom et aux types d'argument donnés. Vous devrez peut-être ajouter des transtypages de types explicites."
Alex
Quelle version de PostgreSQL? Voici la documentation pour la version 9.1: postgresql.org/docs/9.1/static/functions-string.html . Voir mon exemple: sqlfiddle.com/#!15/d41d8/182
PM 77-1
Vous avez probablement une erreur de syntaxe dans votre requête non liée à la concaténation.
PM 77-1

Réponses:

260

Avec des colonnes de type chaîne comme character(2)(comme vous l'avez mentionné plus tard), la concaténation affichée fonctionne simplement parce que, citant le manuel:

[...] l'opérateur de concaténation de chaîne ( ||) accepte une entrée non chaîne, à condition qu'au moins une entrée soit de type chaîne , comme indiqué dans le Tableau 9.8 . Pour les autres cas, insérez une contrainte explicite pour text[...]

Je souligne le mien. Le deuxième exemple ( select a||', '||b from foo) fonctionne pour tous les types de données puisque la chaîne littérale non typée ', 'est par défaut de type, textce qui rend l'expression entière valide dans tous les cas.

Pour les types de données non-chaîne, vous pouvez "corriger" la première instruction en convertissant au moins un argument en text. ( Tout type peut être converti en text):

SELECT a::text || b AS ab FROM foo;

A en juger d'après votre propre réponse , " ne fonctionne pas " était censé signifier " renvoie NULL ". Le résultat de tout ce qui est concaténé à NULL est NULL. Si des valeurs NULL peuvent être impliquées et que le résultat ne doit pas être NULL, utilisez concat_ws()pour concaténer n'importe quel nombre de valeurs (Postgres 9.1 ou version ultérieure):

SELECT concat_ws(', ', a, b) AS ab FROM foo;

Ou concat()si vous n'avez pas besoin de séparateurs:

SELECT concat(a, b) AS ab FROM foo;

Pas besoin de casts de type ici puisque les deux fonctions prennent des "any"entrées et fonctionnent avec des représentations textuelles.

Plus de détails (et pourquoi COALESCEest un mauvais substitut) dans cette réponse connexe:

Concernant la mise à jour dans le commentaire

+n'est pas un opérateur valide pour la concaténation de chaînes dans Postgres (ou SQL standard). C'est une idée privée de Microsoft d'ajouter cela à ses produits.

Il n'y a pratiquement aucune bonne raison d'utiliser character(n)(synonyme:) char(n). Utilisez textouvarchar . Détails:

Erwin Brandstetter
la source
Je vous remercie. La 1ère version ne fonctionne pas avec null et la 2ème m'a donné l'erreur pour concat_ws: Aucune fonction ne correspond au nom et aux types d'argument donnés. Vous devrez peut-être ajouter des casts de types explicites.
Alex
1
Vous avez vu Postgres 9.1 or later, non? Vous devriez avoir fourni votre version de Postgres pour commencer, dans la question . Veuillez mettre à jour votre question avec toutes les informations demandées, avant de revenir pour autre chose.
Erwin Brandstetter
Merci, la solution que j'ai trouvée fonctionne pour n'importe quelle version de Postgres
Alex
SELECT concat(a, b) FROM foo;fonctionne pour moi dans Postgres 9.3 quand aet bsont VARCHARs.
élimiste le
Merci pour votre réponse, cela a résolu mon problème :).
ashwaqar
33

Le problème était dans les valeurs nulles; alors la concaténation ne fonctionne pas avec les valeurs nulles. La solution est la suivante:

SELECT coalesce(a, '') || coalesce(b, '') FROM foo;
Alex
la source
18

il est préférable d'utiliser la fonction CONCAT dans PostgreSQL pour la concaténation

par exemple : select CONCAT(first_name,last_name) from person where pid = 136

si vous utilisez column_a || '' || column_b pour la concaténation pour 2 colonnes, si l'une des valeurs de column_a ou column_b est nulle, la requête retournera une valeur nulle. qui peut ne pas être préféré dans tous les cas .. donc au lieu de cela

||

utilisation

CONCAT

il renverra une valeur pertinente si l'un d'eux a une valeur

arjun nagathankandy
la source
7

Les fonctions CONCAT ne fonctionnent parfois pas avec les anciennes versions de PostgreSQL

voir ce que j'ai utilisé pour résoudre le problème sans utiliser CONCAT

 u.first_name || ' ' || u.last_name as user,

Ou aussi vous pouvez utiliser

 "first_name" || ' ' || "last_name" as user,

dans le second cas, j'ai utilisé des guillemets doubles pour prénom et nom

J'espère que cela sera utile, merci

Rameshwar Vyevhare
la source
1
si mon prénom ou mon nom est nul, alors la valeur de concat affiche également nulle
Lokesh
2

Comme j'étais également coincé là-dedans, je pense que je devrais partager la solution qui fonctionnait le mieux pour moi. Je pense aussi que c'est beaucoup plus simple.

Si vous utilisez un nom de table en majuscules.

SELECT CONCAT("firstName", ' ', "lastName") FROM "User"

Si vous utilisez un nom de table en minuscules

SELECT CONCAT(firstName, ' ', lastName) FROM user

C'est tout!. Comme PGSQL compte Double Quote pour la déclaration de colonne et Single Quote pour la chaîne, cela fonctionne comme un charme.

Rakib Uddin
la source
1

Framework Laravel de PHP, j'utilise la recherche first_name, last_name Les champs sont considérés comme la recherche par nom complet

Utilisation || symbol Ou méthodes concat_ws (), concat ()

$names = str_replace(" ", "", $searchKey);                               
$customers = Customer::where('organization_id',$this->user->organization_id)
             ->where(function ($q) use ($searchKey, $names) {
                 $q->orWhere('phone_number', 'ilike', "%{$searchKey}%"); 
                 $q->orWhere('email', 'ilike', "%{$searchKey}%");
                 $q->orWhereRaw('(first_name || last_name) LIKE ? ', '%' . $names. '%');
    })->orderBy('created_at','desc')->paginate(20);

Ce charme a fonctionné !!!

venkatskpi
la source
0

Essaye ça

select textcat(textcat(FirstName,' '),LastName) AS Name from person;
Muhammad Sadiq
la source
8
concat_ws(' ', FirstName, LastName)serait beaucoup plus propre.
a_horse_with_no_name
-1

Par exemple, s'il existe une table des employés composée de colonnes comme:

employee_number,f_name,l_name,email_id,phone_number 

si nous voulons concaténer f_name + l_namecomme name.

SELECT employee_number,f_name ::TEXT ||','|| l_name::TEXT  AS "NAME",email_id,phone_number,designation FROM EMPLOYEE;
Abhishek Mitra
la source
Qu'est-ce que cette réponse ajoute par rapport aux réponses existantes?
Erwin Brandstetter