Come concatenare le colonne in un SELECT di Postgres?


145

Ho due colonne di stringhe ae bin una tabella foo.

select a, b from foorestituisce valori ae b. Tuttavia, la concatenazione di ae bnon funziona. Provai :

select a || b from foo

e

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

Aggiornamento dai commenti: entrambe le colonne sono di tipo character(2).


... o un altro texttipo?
PM 77-1

@acfrancis Poiché OP dice concatenateche dubito che abbia a che fare con tipi numerici, anche se PostgreSQL si occuperà anche di alcuni di essi. Vedi qui: postgresql.org/docs/9.1/static/functions-string.html
PM 77-1

Sì, queste colonne sono carattere (2). "+" non funziona - "Nessun operatore corrisponde al nome e ai tipi di argomento indicati. Potrebbe essere necessario aggiungere cast di tipi espliciti."
Alex,

Quale versione di PostgreSQL? Ecco i documenti per 9.1: postgresql.org/docs/9.1/static/functions-string.html . Vedi il mio esempio: sqlfiddle.com/#!15/d41d8/182
PM 77-1

Probabilmente hai un errore di sintassi nella tua query non correlato alla concatenazione.
PM 77-1,

Risposte:


260

Con colonne di tipo stringa come character(2)(come menzionato più avanti), la concatenazione visualizzata funziona solo perché, citando il manuale:

[...] l'operatore di concatenazione di stringhe ( ||) accetta input non stringa, purché almeno un input sia di tipo stringa , come mostrato nella Tabella 9.8 . Per altri casi, inserire una coercizione esplicita a text[...]

Enorme enfasi sulla mia. Il 2o esempio ( select a||', '||b from foo) funziona per qualsiasi tipo di dato poiché la stringa non tipizzata viene impostata per ', 'impostazione predefinita textrendendo l'intera espressione valida in ogni caso.

Per i tipi di dati non stringa, è possibile "correggere" la prima istruzione eseguendo il cast di almeno un argomento text. ( È possibile eseguire il cast di qualsiasi tipo text):

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

A giudicare dalla tua risposta , " non funziona " avrebbe dovuto significare " restituisce NULL ". Il risultato di qualsiasi cosa concatenata a NULL è NULL. Se possono essere coinvolti valori NULL e il risultato non deve essere NULL, utilizzare concat_ws()per concatenare un numero qualsiasi di valori (Postgres 9.1 o successivo):

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

O concat()se non hai bisogno di separatori:

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

Non è necessario eseguire il cast di tipi qui poiché entrambe le funzioni accettano "any"input e funzionano con rappresentazioni di testo.

Maggiori dettagli (e perché COALESCEè un cattivo sostituto) in questa risposta correlata:

Per quanto riguarda l'aggiornamento nel commento

+non è un operatore valido per la concatenazione di stringhe in Postgres (o SQL standard). È un'idea privata di Microsoft aggiungere questo ai loro prodotti.

Non c'è quasi nessun buon motivo per usare character(n)(sinonimo:) char(n). Usa textovarchar . Dettagli:


Grazie. La prima versione non funziona con null e la seconda mi ha dato l'errore per concat_ws: nessuna funzione corrisponde al nome e ai tipi di argomento indicati. Potrebbe essere necessario aggiungere cast di tipo esplicito.
Alex,

1
Hai visto Postgres 9.1 or later, vero? Dovresti aver fornito la tua versione di Postgres per cominciare, nella domanda . Ti preghiamo di aggiornare la tua domanda con tutte le informazioni richieste, prima di tornare per qualsiasi altra cosa.
Erwin Brandstetter,

Grazie, la soluzione che ho trovato funziona per qualsiasi versione di Postgres
Alex,

SELECT concat(a, b) FROM foo;funziona per me in Postgres 9.3 quando ae bsono VARCHARs.
elimisteve,

Grazie per la tua risposta, ha risolto il mio problema :).
ashwaqar,

33

Il problema era nei valori nulli; quindi la concatenazione non funziona con valori null. La soluzione è la seguente:

SELECT coalesce(a, '') || coalesce(b, '') FROM foo;

18

è meglio usare la funzione CONCAT in PostgreSQL per la concatenazione

per esempio : select CONCAT(first_name,last_name) from person where pid = 136

se stai usando column_a || '' || column_b per la concatenazione per 2 colonne, se uno qualsiasi dei valori in column_a o column_b è null, la query restituirà un valore null. che potrebbe non essere preferito in tutti i casi .. quindi invece di questo

||

uso

CONCAT

restituirà un valore rilevante se uno di essi ha un valore


7

Le funzioni CONCAT a volte non funzionano con la versione postgreSQL precedente

vedi cosa ho usato per risolvere il problema senza usare CONCAT

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

O anche tu puoi usare

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

nel secondo caso ho usato le virgolette doppie per first_name e last_name

Spero che questo sia utile, grazie


1
se il mio nome o cognome è null, il valore concat mostra anche null
Lokesh

2

Dato che ero anche bloccato in questo, penso che dovrei condividere la soluzione che ha funzionato meglio per me. Penso anche che sia molto più semplice.

Se si utilizza il nome della tabella in maiuscolo.

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

Se si utilizza il nome della tabella in minuscolo

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

Questo è tutto!. Dato che PGSQL conta le virgolette doppie per la dichiarazione delle colonne e le virgolette singole per la stringa, questo funziona come un incantesimo.


1

Framework Laravel di PHP, sto usando la ricerca first_name, last_name I campi considerano come Ricerca per nome completo

Utilizzando || simbolo O metodi 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);

Questo fascino ha funzionato !!!



-1

Ad esempio, se esiste una tabella dei dipendenti composta da colonne come:

employee_number,f_name,l_name,email_id,phone_number 

se vogliamo concatenare f_name + l_namecome name.

SELECT employee_number,f_name ::TEXT ||','|| l_name::TEXT  AS "NAME",email_id,phone_number,designation FROM EMPLOYEE;

Cosa aggiunge questa risposta alle risposte esistenti?
Erwin Brandstetter,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.