Wie verkette ich Spalten in einem Postgres SELECT?

145

Ich habe zwei String-Spalten aund bin einer Tabelle foo.

select a, b from foogibt Werte aund zurück b. Die Verkettung von aund bfunktioniert jedoch nicht. Ich habe es versucht :

select a || b from foo

und

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

Update aus Kommentaren: Beide Spalten sind vom Typ character(2).

Alex
quelle
... oder ein anderer textTyp?
PM 77-1
@acfrancis Da OP sagt, concatenatebezweifle ich, dass er sich mit numerischen Typen befasst, obwohl PostgreSQL sich auch um einige von ihnen kümmern würde. Siehe hier: postgresql.org/docs/9.1/static/functions-string.html
PM 77-1
Ja, diese Spalten sind Zeichen (2). "+" funktioniert nicht - "Kein Operator stimmt mit dem angegebenen Namen und den angegebenen Argumenttypen überein. Möglicherweise müssen Sie explizite Typumwandlungen hinzufügen."
Alex
Welche Version von PostgreSQL? Hier sind Dokumente für 9.1: postgresql.org/docs/9.1/static/functions-string.html . Siehe mein Beispiel: sqlfiddle.com/#!15/d41d8/182
PM 77-1
Sie haben wahrscheinlich einen Syntaxfehler in Ihrer Abfrage, der nicht mit der Verkettung zusammenhängt.
PM 77-1

Antworten:

260

Bei Spalten vom Typ Zeichenfolge wie character(2)(wie Sie später erwähnt haben) funktioniert die angezeigte Verkettung nur, weil unter Berufung auf das Handbuch:

[...] Der String-Verkettungsoperator ( ||) akzeptiert Eingaben ohne String, solange mindestens eine Eingabe vom Typ String ist (siehe Tabelle 9.8) . Fügen Sie in anderen Fällen einen expliziten Zwang ein, um text[...]

Meine kühne Betonung. Das zweite Beispiel ( select a||', '||b from foo) funktioniert für alle Datentypen, da das nicht typisierte Zeichenfolgenliteral ', 'standardmäßig den Typ angibt, textsodass der gesamte Ausdruck in jedem Fall gültig ist.

Bei Datentypen ohne Zeichenfolge können Sie die erste Anweisung "korrigieren", indem Sie mindestens ein Argument in " Casting " umwandeln text. ( Jeder Typ kann gegossen werden text):

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

Nach Ihrer eigenen Antwort zu urteilen , sollte " funktioniert nicht " " NULL zurückgeben " bedeuten . Das Ergebnis von allem, was mit NULL verkettet ist, ist NULL. Wenn NULL- Werte beteiligt sein können und das Ergebnis nicht NULL sein soll, verwenden Sie diese Option, um concat_ws()eine beliebige Anzahl von Werten zu verketten (Postgres 9.1 oder höher):

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

Oder concat()wenn Sie keine Trennzeichen benötigen:

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

Hier sind keine Typumwandlungen erforderlich, da beide Funktionen "any"Eingaben vornehmen und mit Textdarstellungen arbeiten.

Weitere Details (und warum COALESCEist ein schlechter Ersatz) in dieser verwandten Antwort:

Zum Update im Kommentar

+ist kein gültiger Operator für die Verkettung von Zeichenfolgen in Postgres (oder Standard-SQL). Es ist eine private Idee von Microsoft, dies zu ihren Produkten hinzuzufügen.

Es gibt kaum einen guten Grund character(n)(synonym :) char(n). Verwenden Sie textodervarchar . Einzelheiten:

Erwin Brandstetter
quelle
Danke dir. Die 1. Version funktioniert nicht mit null und die 2. gab mir den Fehler für concat_ws: Keine Funktion stimmt mit dem angegebenen Namen und den angegebenen Argumenttypen überein. Möglicherweise müssen Sie explizite Typumwandlungen hinzufügen.
Alex
1
Du hast gesehen Postgres 9.1 or later, richtig? Sie sollten in der Frage zunächst Ihre Version von Postgres angegeben haben . Bitte aktualisieren Sie Ihre Frage mit allen angeforderten Informationen, bevor Sie für etwas anderes zurückkommen.
Erwin Brandstetter
Vielen Dank, die Lösung, die ich gefunden habe, funktioniert für jede Postgres-Version
Alex
SELECT concat(a, b) FROM foo;arbeitet für mich in Postgres 9.3 wann aund bsind VARCHARs.
Elimisteve
Vielen Dank für Ihre Antwort, es hat mein Problem gelöst :).
Ashwaqar
33

Das Problem war in Nullen in den Werten; dann funktioniert die Verkettung nicht mit Nullen. Die Lösung lautet wie folgt:

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

Es ist besser, die CONCAT-Funktion in PostgreSQL zur Verkettung zu verwenden

z.B : select CONCAT(first_name,last_name) from person where pid = 136

wenn Sie column_a || verwenden '' || column_b für die Verkettung von 2 Spalten. Wenn einer der Werte in column_a oder column_b null ist, gibt die Abfrage den Wert null zurück. was möglicherweise nicht in allen Fällen bevorzugt wird .. also stattdessen

||

verwenden

CONCAT

Es wird einen relevanten Wert zurückgeben, wenn einer von beiden einen Wert hat

Arjun Nagathankandy
quelle
7

CONCAT-Funktionen funktionieren manchmal nicht mit älteren postgreSQL-Versionen

Sehen Sie, was ich verwendet habe, um das Problem ohne CONCAT zu lösen

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

Oder Sie können auch verwenden

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

im zweiten Fall habe ich doppelte Anführungszeichen für Vorname und Nachname verwendet

Hoffe das wird nützlich sein, danke

Rameshwar Vyevhare
quelle
1
Wenn mein Vor- oder Nachname null ist, zeigt der Concat-Wert ebenfalls null an
Lokesh
2

Da ich auch darin feststeckte, denke ich, ich sollte die Lösung teilen, die für mich am besten funktioniert hat. Ich denke auch, dass dies viel einfacher ist.

Wenn Sie den Namen der großgeschriebenen Tabelle verwenden.

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

Wenn Sie den Tabellennamen in Kleinbuchstaben verwenden

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

Das ist es!. Da PGSQL Double Quote für die Spaltendeklaration und Single Quote für die Zeichenfolge zählt, funktioniert dies wie ein Zauber.

Rakib Uddin
quelle
1

PHPs Laravel-Framework, ich verwende die Suche Vorname, Nachname Felder betrachten wie die vollständige Namenssuche

Verwenden von || symbol Oder concat_ws (), concat () Methoden

$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);

Das hat Charme geklappt !!!

venkatskpi
quelle
0

Versuche dies

select textcat(textcat(FirstName,' '),LastName) AS Name from person;
Muhammad Sadiq
quelle
8
concat_ws(' ', FirstName, LastName)wäre viel sauberer.
a_horse_with_no_name
-1

Zum Beispiel, wenn es eine Mitarbeitertabelle gibt, die aus folgenden Spalten besteht:

employee_number,f_name,l_name,email_id,phone_number 

wenn wir f_name + l_nameals verketten wollen name.

SELECT employee_number,f_name ::TEXT ||','|| l_name::TEXT  AS "NAME",email_id,phone_number,designation FROM EMPLOYEE;
Abhishek Mitra
quelle
Was fügt diese Antwort den vorhandenen Antworten hinzu?
Erwin Brandstetter