Serait-il possible de construire SQL pour concaténer les valeurs de colonne à partir de plusieurs lignes?
Ce qui suit est un exemple:
Tableau A
PID UNE B C
Tableau B
Desc. PID SEQ A 1 ont A 2 un joli A 3 jours. B 1 Beau travail. C 1 Oui C 2 on peut C 3 faire C 4 ce travail!
La sortie du SQL doit être -
Desc PID A Passez une bonne journée. B Beau travail. C Oui, nous pouvons faire ce travail!
Donc, fondamentalement, la colonne Desc pour la table de sortie est une concaténation des valeurs SEQ de la table B?
Une aide avec le SQL?
sql
oracle
string-aggregation
jagamot
la source
la source
Réponses:
Il existe plusieurs façons selon la version que vous avez - voir la documentation d'Oracle sur les techniques d'agrégation de chaînes . Un très courant est d'utiliser
LISTAGG
:Ensuite, rejoignez pour
A
choisir celui quepids
vous voulez.Remarque: prêt à l'emploi,
LISTAGG
ne fonctionne correctement qu'avec lesVARCHAR2
colonnes.la source
Il existe également une
XMLAGG
fonction, qui fonctionne sur les versions antérieures à 11.2. Étant donné qu'ilWM_CONCAT
n'est ni documenté ni pris en charge par Oracle , il est recommandé de ne pas l'utiliser dans le système de production.Avec
XMLAGG
vous pouvez faire ce qui suit:Ce que cela fait est
ename
colonne (concaténée avec une virgule) duemployee_names
tableau dans un élément xml (avec la balise E)la source
Avec la clause de modèle SQL:
J'ai écrit à ce sujet ici . Et si vous suivez le lien vers le thread OTN, vous en trouverez d'autres, y compris une comparaison des performances.
la source
La fonction analytique LISTAGG a été introduite dans Oracle 11g Release 2 , ce qui rend très facile l'agrégation des chaînes. Si vous utilisez 11g Release 2, vous devez utiliser cette fonction pour l'agrégation de chaînes. Veuillez vous référer à l'url ci-dessous pour plus d'informations sur la concaténation de chaînes.
http://www.oracle-base.com/articles/misc/StringAggregationTechniques.php
Concaténation de chaînes
la source
Comme la plupart des réponses le suggèrent,
LISTAGG
c'est l'option évidente. Cependant, un aspect ennuyeux avecLISTAGG
est que si la longueur totale de la chaîne concaténée dépasse 4000 caractères (limite pourVARCHAR2
SQL), l'erreur ci-dessous est renvoyée, ce qui est difficile à gérer dans les versions d'Oracle jusqu'à 12.1Une nouvelle fonctionnalité ajoutée dans 12cR2 est la
ON OVERFLOW
clause deLISTAGG
. La requête comprenant cette clause ressemblerait à ceci:Ce qui précède limitera la sortie à 4000 caractères mais ne lèvera pas l'
ORA-01489
erreur.Voici quelques-unes des options supplémentaires de la
ON OVERFLOW
clause:ON OVERFLOW TRUNCATE 'Contd..'
: Ceci s'affichera'Contd..'
à la fin de la chaîne (la valeur par défaut est...
)ON OVERFLOW TRUNCATE ''
: Cela affichera les 4000 caractères sans aucune chaîne de fin.ON OVERFLOW TRUNCATE WITH COUNT
: Ceci affichera le nombre total de caractères à la fin après les caractères de fin. Par exemple: - '...(5512)
'ON OVERFLOW ERROR
: Si vous vous attendez à ce que leLISTAGG
échoue avec l'ORA-01489
erreur (qui est par défaut de toute façon).la source
Pour ceux qui doivent résoudre ce problème à l'aide d'Oracle 9i (ou version antérieure), vous devrez probablement utiliser SYS_CONNECT_BY_PATH, car LISTAGG n'est pas disponible.
Pour répondre à l'OP, la requête suivante affichera le PID du tableau A et concaténera toutes les colonnes DESC du tableau B:
Il peut également y avoir des cas où les clés et les valeurs sont toutes contenues dans une table. La requête suivante peut être utilisée lorsqu'il n'y a pas de table A et que seule la table B existe:
Toutes les valeurs peuvent être réorganisées comme vous le souhaitez. Les descriptions concaténées individuelles peuvent être réorganisées dans la clause PARTITION BY, et la liste des PID peut être réorganisée dans la clause ORDER BY finale.
Alternativement: il peut arriver que vous souhaitiez concaténer toutes les valeurs d'une table entière en une seule ligne.
L'idée clé ici est d'utiliser une valeur artificielle pour le groupe de descriptions à concaténer.
Dans la requête suivante, la chaîne constante «1» est utilisée, mais toute valeur fonctionnera:
Les descriptions concaténées individuelles peuvent être réorganisées dans la clause PARTITION BY.
Plusieurs autres réponses sur cette page ont également mentionné cette référence extrêmement utile: https://oracle-base.com/articles/misc/string-aggregation-techniques
la source
LISTAGG offre les meilleures performances si le tri est indispensable (00: 00: 05.85)
SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description FROM B GROUP BY pid;
COLLECT offre les meilleures performances si le tri n'est pas nécessaire (00: 00: 02.90):
SELECT pid, TO_STRING(CAST(COLLECT(Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;
COLLECT avec commande est un peu plus lent (00: 00: 07.08):
SELECT pid, TO_STRING(CAST(COLLECT(Desc ORDER BY Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;
Toutes les autres techniques étaient plus lentes.
la source
Avant d'exécuter une requête de sélection, exécutez ceci:
SET SERVEROUT ON SIZE 6000
la source
Essayez ce code:
la source
Dans le sélectionnez où vous voulez votre concaténation, appelez une fonction SQL.
Par exemple:
Puis pour la fonction SQL:
La syntaxe de l'en-tête de fonction peut être incorrecte, mais le principe fonctionne.
la source