web-dev-qa-db-fra.com

Sortie DB2 séparée par des virgules

Comment obtenir une fonction intégrée pour les valeurs de colonne séparées par des virgules dans sql Dans DB2, par exemple, s'il existe des colonnes avec cet ID de règle et si elle a 3 lignes avec le même identifiant mais trois rôles différents sur 3 rangées, alors récupérer les lignes d'une ligne "3,4,5"

par exemple.

1. 4555 "2"
2. 4555 "3"
3. 4555 "4"

4555 2,3,4 en sortie dans une base de données DB2 sur une ligne

13
gaurav

LISTAGGfunction est une nouvelle fonction dans DB2 LUW 9.7

voir exemple:

create table myTable (id int, category int);

insert into myTable values (1, 1);
insert into myTable values (2, 2);
insert into myTable values (5, 1);
insert into myTable values (3, 1);
insert into myTable values (4, 2);

exemple: sélectionne sans ordre dans la colonne groupée

select category, LISTAGG(id, ', ') as ids from myTable group by category;

résultat:

CATEGORY  IDS
--------- -----
1         1, 5, 3
2         2, 4

exemple: select with order by dans une colonne groupée

select
  category,
  LISTAGG(id, ', ') WITHIN GROUP(ORDER BY id ASC) as ids
from myTable
group by category;

résultat:

CATEGORY  IDS
--------- -----
1         1, 3, 5
2         2, 4
31
Fernando

Je pense qu'avec cette petite requête, vous pouvez faire ce que vous voulez. Cela équivaut à GROUP_CONCAT de MySQL dans DB2. 

SELECT 
NUM, 
SUBSTR(xmlserialize(xmlagg(xmltext(CONCAT( ', ',ROLES))) as VARCHAR(1024)), 3) as ROLES
FROM mytable 
GROUP BY NUM;

Cela produira quelque chose comme: 

NUM   ROLES
----  -------------
1     111, 333, 555
2     222, 444

assumer votre résultat initial était quelque chose comme ça:

NUM   ROLES
----  ---------
1     111
2     222
1     333
2     444
1     555
10
Nicki Voutou

Selon la version de DB2 dont vous disposez, vous pouvez utiliser les fonctions XML pour y parvenir.

Exemple de table avec des données

create table myTable (id int, category int);
insert into myTable values (1, 1);
insert into myTable values (2, 2);
insert into myTable values (3, 1);
insert into myTable values (4, 2);
insert into myTable values (5, 1);

Agréger les résultats à l'aide de fonctions xml

select category, 
    xmlserialize(XMLAGG(XMLELEMENT(NAME "x", id) ) as varchar(1000)) as ids 
    from myTable
    group by category;

résultats:

CATEGORY IDS
 -------- ------------------------
        1 <x>1</x><x>3</x><x>5</x>
        2 <x>2</x><x>4</x>

Utilisez replace pour améliorer le résultat

select category, 
        replace(
        replace(
        replace(
            xmlserialize(XMLAGG(XMLELEMENT(NAME "x", id) ) as varchar(1000))
            , '</x><x>', ',')
            , '<x>', '')
            , '</x>', '') as ids 
    from myTable
    group by category;

Résultat nettoyé

CATEGORY IDS
 -------- -----
        1 1,3,5
        2 2,4

Je viens de voir une meilleure solution utilisant XMLTEXT au lieu de XMLELEMENT ici .

8
boes

Depuis DB2 9.7.5, il existe une fonction pour cela: 

LISTAGG(colname, separator)

vérifiez ceci pour plus d'informations: Utilisation de LISTAGG pour transformer des lignes de données en une liste séparée par des virgules

1
Gomez NL

Mon problème était de transposer des champs de ligne (CLOB) en colonne (VARCHAR) avec un fichier CSV et d'utiliser la table transposée pour la génération de rapports. Parce que la transposition sur la couche de rapport ralentit le rapport. 

Une solution consiste à utiliser du SQL récursif. Vous pouvez trouver de nombreux articles à ce sujet, mais il est difficile et prend beaucoup de ressources si vous souhaitez joindre toutes vos colonnes transposées récursives.

J'ai créé plusieurs tables temporaires globales dans lesquelles je stockais des colonnes transposées uniques avec un identifiant de clé. Finalement, j'ai eu 6 tables temporaires pour joindre 6 colonnes, mais en raison de l'allocation de ressources limitée, je n'ai pas pu rassembler toutes les colonnes. J'ai opté pour moins de 3 formules puis il me suffisait d'exécuter une requête qui me donnait une sortie en 10 secondes.

J'ai trouvé divers articles sur l'utilisation des fonctions XML2CLOB et j'ai trouvé 3 façons différentes.

REPLACE (VARCHAR (XML2CLOB (XMLAGG (XMLELEMENT (NOM "A"), ALIASNAME.ATTRIBUTENAME)))), '', ',') TRANSPOSED_OUTPUT 
NVL (TRIM (',' FROM REPLACE (REMPLACE (REMPLACE (CAST (XML2CLOB)), XMLAGG (XMLELEMENT (NOM "E", ALIASNAME.ATTRIBUTENAME)) AS VARCHAR (100)), '', '' '),' ', ','), '', 'Rien')), 'Rien') comme TRANSPOSED_OUTPUT 
 RTRIM (REMPLACE (REMPLACE (REMPLACE (VARCHAR (XMLSERIALIZE (XMLAGG (X)) (XMLELEMENT (NOM "A", ALIASNAME.ATTRIBUTENAME) ORDER PAR ALIASNAME.ATTRIBUTENAME), ',', ','), ',' '),' ',' ') AS TRANSPOSED_OUTPUT 

Assurez-vous que vous lancez votre "ATTRIBUTENAME" dans varchar dans une sous-requête, puis appelez-le ici.

0
Bhavesh

autre possibilité, avec cte récursive

    with tablewithrank as (
    select id, category, rownumber() over(partition by category order by id) as rangid , (select count(*) from  myTable f2 where f1.category=f2.category) nbidbycategory
    from myTable f1
    ),
    cte (id, category, rangid, nbidbycategory, rangconcat) as (
    select id, category, rangid, nbidbycategory, cast(id as varchar(500)) from tablewithrank where rangid=1
    union all 
    select  f2.id, f2.category, f2.rangid, f2.nbidbycategory, cast(f1.rangconcat as varchar(500)) || ',' || cast(f2.id as varchar(500)) from cte f1 inner join tablewithrank f2 on f1.rangid=f2.rangid -1 and f1.category=f2.category
    )
    select category, rangconcat as IDS  from cte
    where rangid=nbidbycategory
0
Esperento57