Frage

Ist es möglich, SQL zu verketten Spaltenwerte zu konstruieren aus mehrere Zeilen?

Im Folgenden ist ein Beispiel:

Tabelle A

PID
A
B
C

Tabelle B

PID   SEQ    Desc

A     1      Have
A     2      a nice
A     3      day.
B     1      Nice Work.
C     1      Yes
C     2      we can 
C     3      do 
C     4      this work!

Ausgabe des SQL sollte -

PID   Desc
A     Have a nice day.
B     Nice Work.
C     Yes we can do this work!

Also im Grunde die Beschr Spalte für out Put-Tabelle ist eine Verkettung der SEQ Werte aus Tabelle B?

Jede mögliche Hilfe bei der SQL?

War es hilfreich?

Lösung

Es gibt ein paar Möglichkeiten, je nachdem, welche Version Sie haben - siehe Oracle-Dokumentation auf String Aggregationstechniken. Ein sehr häufig ist LISTAGG :

SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description
FROM B GROUP BY pid;

kommen dann zu A die pids herauszupicken Sie wollen.

. Hinweis: Aus dem Kasten heraus, LISTAGG funktioniert nur korrekt mit VARCHAR2 Spalten

Andere Tipps

Es gibt auch eine XMLAGG Funktion, die vor 11.2 auf Versionen funktioniert. Da WM_CONCAT undokumentierte und nicht unterstützte von Oracle , wird empfohlen, nicht in Produktionssystem zu verwenden.

Mit XMLAGG können Sie Folgendes tun:

SELECT XMLAGG(XMLELEMENT(E,ename||',')).EXTRACT('//text()') "Result" 
FROM employee_names

Was das bedeutet ist

  • stellt die Werte der ename Säule (mit einem Komma konkateniert) von der employee_names Tabelle in einem XML-Elemente (mit Tag E)
  • extrahiert den Text dieses
  • aggregieren die XML (verketten it)
  • rufen Sie die resultierende Spalte "Result"

Mit SQL-Modell-Klausel:

SQL> select pid
  2       , ltrim(sentence) sentence
  3    from ( select pid
  4                , seq
  5                , sentence
  6             from b
  7            model
  8                  partition by (pid)
  9                  dimension by (seq)
 10                  measures (descr,cast(null as varchar2(100)) as sentence)
 11                  ( sentence[any] order by seq desc
 12                    = descr[cv()] || ' ' || sentence[cv()+1]
 13                  )
 14         )
 15   where seq = 1
 16  /

P SENTENCE
- ---------------------------------------------------------------------------
A Have a nice day
B Nice Work.
C Yes we can do this work!

3 rows selected.

Ich schrieb über dieses hier . Und wenn Sie den Link zum OTN-Thread folgen, werden Sie einige weitere, darunter ein Leistungsvergleich finden.

Die LISTAGG analytische Funktion wurde eingeführt Oracle 11g Release 2 , ist es sehr einfach zu aggregieren Saiten machen. Wenn Sie 11g Release 2 verwenden, sollten Sie diese Funktion für die Zeichenfolge Aggregation verwenden. Bitte beziehen Sie sich unter URL für weitere Informationen über die String-Verkettung.

http://www.oracle-base.com/articles/misc/ StringAggregationTechniques.php

String Concatenation

Wie die meisten Antworten vorschlagen, ist LISTAGG die offensichtliche Wahl. Doch mit LISTAGG ein ärgerlicher Aspekt ist, dass, wenn die Gesamtlänge der verketteten Zeichenfolge überschreitet 4000 Zeichen (Limit für VARCHAR2 in SQL), wird die unten Fehler ausgelöst, die nur schwer in Oracle-Versionen bis 12.1

verwalten

ORA-01489: Ergebnis der Stringverkettung zu lang

Ein neues Feature in 12cR2 hinzugefügt ist die ON OVERFLOW Klausel LISTAGG. Die Abfrage dieser Klausel einschließlich würde wie folgt aussehen:

SELECT pid, LISTAGG(Desc, ' ' on overflow truncate) WITHIN GROUP (ORDER BY seq) AS desc
FROM B GROUP BY pid;

Das oben wird die Ausgabe auf 4000 Zeichen beschränken, sondern die ORA-01489 Fehler nicht werfen.

Dies sind nur einige der zusätzlichen Optionen von ON OVERFLOW-Klausel:

  • ON OVERFLOW TRUNCATE 'Contd..': Dies wird angezeigt 'Contd..' an das Ende der Zeichenfolge (Standard ist ...)
  • ON OVERFLOW TRUNCATE '': Das wird die 4000 Zeichen angezeigt werden ohne Abschluss String.
  • ON OVERFLOW TRUNCATE WITH COUNT: Damit erhöht sich die Anzeige Anzahl der Zeichen am Ende nach dem Abschlusszeichen. ZB: - '...(5512)'
  • ON OVERFLOW ERROR: Wenn Sie die LISTAGG scheitern mit der erwarten ORA-01489 Fehler (der Standard sowieso).

Für diejenigen, die dieses Problem mit Oracle 9i lösen muss (oder früher), werden Sie wahrscheinlich zu verwenden SYS_CONNECT_BY_PATH benötigen, da LISTAGG nicht verfügbar ist.

, um die OP zu beantworten, die folgende Abfrage wird die PID aus Tabelle A angezeigt werden und alle die DESC Spalten aus Tabelle B verketten:

SELECT pid, SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions
FROM (
       SELECT ROW_NUMBER () OVER (PARTITION BY pid ORDER BY pid, seq) rnum, pid, description
       FROM (
              SELECT a.pid, seq, description
              FROM table_a a, table_b b
              WHERE a.pid = b.pid(+)
             )
      )
START WITH rnum = 1
CONNECT BY PRIOR rnum = rnum - 1 AND PRIOR pid = pid
GROUP BY pid
ORDER BY pid;

Es gibt auch Fälle geben kann, in denen Schlüssel und Werte sind alle in einer Tabelle enthalten. Die folgende Abfrage kann verwendet werden, in denen es keine Tabelle A ist, und nur Tabelle B vorhanden ist:

SELECT pid, SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions
FROM (
       SELECT ROW_NUMBER () OVER (PARTITION BY pid ORDER BY pid, seq) rnum, pid, description
       FROM (
              SELECT pid, seq, description
              FROM table_b
             )
      )
START WITH rnum = 1
CONNECT BY PRIOR rnum = rnum - 1 AND PRIOR pid = pid
GROUP BY pid
ORDER BY pid;

können alle Werte neu geordnet werden, wie gewünscht. Einzelne verketteten Beschreibungen können in der PARTITION BY-Klausel und die Liste der PIDs können nachbestellt werden in der endgültigen ORDER BY-Klausel erst nachbestellt werden.


Alternativ:. kann es vorkommen, dass Sie alle die Werte aus einer ganzen Tabelle in einer Zeile verketten möchten

Die Schlüsselidee ist hier ein künstliches Wert für die Gruppe von Beschreibungen mit verketteten werden.

In der folgenden Abfrage, der konstante String '1' verwendet wird, aber jeder Wert funktioniert:

SELECT SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions
FROM (
       SELECT ROW_NUMBER () OVER (PARTITION BY unique_id ORDER BY pid, seq) rnum, description
       FROM (
              SELECT '1' unique_id, b.pid, b.seq, b.description
              FROM table_b b
             )
      )
START WITH rnum = 1
CONNECT BY PRIOR rnum = rnum - 1;

Einzelne verketteten können Beschreibungen in der PARTITION BY-Klausel erst nachbestellt werden.

Mehrere andere Antworten auf dieser Seite erwähnt haben auch diese äußerst hilfreich Referenz: https://oracle-base.com/articles/misc/string-aggregation-techniques

  1. LISTAGG liefert die beste Leistung, wenn das Sortieren ist ein Muss (00: 00: 05.85)

    SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description FROM B GROUP BY pid;

  2. liefert COLLECT die beste Leistung, wenn das Sortieren nicht benötigt wird (00: 00: 02.90):

    SELECT pid, TO_STRING(CAST(COLLECT(Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;

  3. COLLECT mit der Bestellung ist etwas langsamer (00: 00: 07.08):

    SELECT pid, TO_STRING(CAST(COLLECT(Desc ORDER BY Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;

Alle anderen Techniken waren langsamer.

Bevor Sie eine SELECT-Abfrage ausführen, führen diese:

SET SERVEROUT ON SIZE 6000

SELECT XMLAGG(XMLELEMENT(E,SUPLR_SUPLR_ID||',')).EXTRACT('//text()') "SUPPLIER" 
FROM SUPPLIERS;

ich die LISTAGG verwenden, aber diese Zeichenfolge für persisch String zurück!

meine Frage:

SELECT
 listagg(DESCRIPTION,' , ') within group (order by DESCRIPTION) 
FROM
B_CEREMONY

Ergebnis:

'A7'1 , ,4F

Bitte helfen Sie mir.

wow diese Lösung wird gearbeitet:

SELECT listagg(convert(DESCRIPTION, 'UTF8', 'AL16UTF16'),' , ') within group 
(order by DESCRIPTION) 
FROM  B_CEREMONY;

Versuchen Sie diesen Code ein:

 SELECT XMLAGG(XMLELEMENT(E,fieldname||',')).EXTRACT('//text()') "FieldNames"
    FROM FIELD_MASTER
    WHERE FIELD_ID > 10 AND FIELD_AREA != 'NEBRASKA';

In der Auswahl, wo Sie Ihre Verkettung möchten, rufen Sie eine SQL-Funktion.

Zum Beispiel:

select PID, dbo.MyConcat(PID)
   from TableA;

Dann für die SQL-Funktion:

Function MyConcat(@PID varchar(10))
returns varchar(1000)
as
begin

declare @x varchar(1000);

select @x = isnull(@x +',', @x, @x +',') + Desc
  from TableB
    where PID = @PID;

return @x;

end

Die Funktion Kopf Syntax könnte falsch sein, aber das Prinzip funktioniert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top