Domanda

sarebbe possibile costruire SQL per i valori della colonna concatenare da più righe?

Il seguente è un esempio:

Tabella A

PID
A
B
C

Tabella 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!

Output del SQL dovrebbe essere -

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

Quindi, in pratica la colonna Desc per uscire tavolo put è una concatenazione di valori SEQ dalla Tabella B?

Qualsiasi aiuto con SQL?

È stato utile?

Soluzione

Ci sono alcuni modi a seconda di quale versione si ha - vedere la documentazione di Oracle su stringa tecniche di aggregazione . Un molto comune è quello di utilizzare LISTAGG :

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

Poi si uniscono per A di scegliere la pids che si desidera.

Nota. Fuori dalla scatola, LISTAGG funziona correttamente solo con colonne VARCHAR2

Altri suggerimenti

C'è anche una funzione XMLAGG, che funziona su versioni precedenti alla 11.2. Perché WM_CONCAT è non documentata e non supportata da Oracle , si consiglia di non usarlo in sistema di produzione.

Con XMLAGG è possibile effettuare le seguenti operazioni:

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

Quello che fa è

  • inserisce i valori della colonna ename (concatenato con una virgola) dalla tabella employee_names in un elemento XML (con etichetta E)
  • estrarre il testo di questo
  • aggregare l'XML (concatenare esso)
  • chiamare la colonna "Risultato" risultante

Con modello di clausola SQL:

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.

ho scritto su questo qui . E se si segue il link al OTN-filo si trova un po ', tra cui un confronto delle prestazioni.

Il LISTAGG funzione analitica è stata introdotta nel Oracle 11g Release 2 , il che rende molto facile da stringhe di aggregazione. Se si utilizza 11g Release 2 si dovrebbe utilizzare questa funzione per l'aggregazione di stringa. Si prega di fare riferimento al di sotto URL per ulteriori informazioni sulla concatenazione di stringhe.

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

concatenazione di stringhe

Come la maggior parte delle risposte suggeriscono, LISTAGG è l'opzione ovvia. Tuttavia, un aspetto fastidioso con LISTAGG è che se la lunghezza totale della stringa concatenata supera i 4000 caratteri (limite per VARCHAR2 in SQL), l'errore viene generato al di sotto, che è difficile da gestire nelle versioni di Oracle fino a 12,1

ORA-01489: risultato della concatenazione di stringhe è troppo lunga

Una nuova funzionalità aggiunta nel 12cR2 è la clausola di ON OVERFLOW LISTAGG. La query tra cui questa clausola sarà simile:

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

È possibile che questo limiterà l'uscita a 4000 caratteri, ma non getterà l'errore ORA-01489.

Queste sono alcune delle opzioni aggiuntive di clausola ON OVERFLOW:

  • ON OVERFLOW TRUNCATE 'Contd..': Questo mostrerà 'Contd..' a alla fine della stringa (di default è ...)
  • ON OVERFLOW TRUNCATE '': Questo mostrerà i 4000 caratteri senza qualsiasi stringa di terminazione.
  • ON OVERFLOW TRUNCATE WITH COUNT: Questo visualizzerà la totale numero di caratteri alla fine dopo i caratteri di terminazione. Ad esempio: - '...(5512)'
  • ON OVERFLOW ERROR: Se si prevede la LISTAGG a fallire con il Errore di ORA-01489 (che è in ogni caso di default).

Per coloro che devono risolvere questo problema utilizzando Oracle 9i (o precedente), si avrà probabilmente bisogno di usare SYS_CONNECT_BY_PATH, dal momento che LISTAGG non è disponibile.

Per rispondere alla OP, la seguente query visualizzerà il PID dalla Tabella A e concatenare tutte le colonne DESC dalla Tabella B:

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;

Ci possono anche essere casi in cui chiavi e valori sono tutti contenuti in una tabella. La seguente query può essere utilizzata dove non c'è tabella A, e solo Tabella B esiste:

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;

Tutti i valori possono essere riordinati, se lo desideri. Singole descrizioni concatenati possono essere riordinati nella partizione dalla clausola, e la lista dei PID possono essere riordinati in ORDER BY finale.


In alternativa:. ci possono essere momenti in cui si desidera concatenare tutti i valori di un'intera tabella in una riga

L'idea chiave qui è usare un valore artificiale per il gruppo di descrizioni da concatenare.

Nella query seguente, viene utilizzata la stringa costante '1', ma qualsiasi valore funziona:

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;

Individuale concatenato descrizioni possono essere riordinate nella partizione dalla clausola.

Diverse altre risposte in questa pagina hanno anche parlato di questo riferimento estremamente utile: https://oracle-base.com/articles/misc/string-aggregation-techniques

  1. LISTAGG offre le migliori prestazioni se l'ordinamento è un must (00: 00: 05.85)

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

  2. offre la miglior collezione prestazione se l'ordinamento non è necessaria (00: 00: 02.90):

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

  3. Raccogli con l'ordinazione è po 'più lento (00: 00: 07.08):

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

Tutte le altre tecniche erano più lenti.

Prima di eseguire una query di selezione, eseguire questo:

SET SERVEROUT ON SIZE 6000

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

I utilizzando il LISTAGG ma restituire questa stringa per stringa persiano!

la mia domanda:

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

Risultati:

'A7'1 , ,4F

Si prega di aiutare me.

wow questa soluzione è lavorato:

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

Prova questo codice:

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

Nel selezionare dove si desidera che la concatenazione, chiamare una funzione SQL.

Ad esempio:

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

Poi per la funzione SQL:

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

La sintassi Header funzione potrebbe essere sbagliato, ma il principio funziona.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top