2013-07-06 6 views
1

Ma structure de table ressemble à ceci, je suis nouveau pour ce domaine. Je connais les requêtes de base. Mais c'est compliqué pour moi. Aidez-moi s'il vous plaît à faire ceci.Agrégation de chaînes Oracle

Structure de la table

Customer   Product   piriority 
    10001   Main_product 1 
    10001   Sub_product1 2 
    10001   Sub_product2 2 
    10001   Sub_product3 2 
    10001   Sub_product4 2 
    10002   Main_product 1 
    10002   Sub_product1 2 
    10002   Sub_product2 2 

Résultats escomptés:

Customer  Main_Product Sub_product 
10001   Main_product Sub_product1,Sub_product2,Sub_product3,Sub_product4 
10002   Main_product Sub_product1,Sub_product2 

Répondre

5

Je vais supposer que la colonne PRIORITY est toujours 1 quand il y a un "produit principal" et jamais 1 toute autre fois. De vos données, il semble également que chaque client n'a qu'un seul produit "principal". Je vais supposer que c'est vrai. Si ce n'est pas le cas, vous devriez avoir une autre colonne pour distinguer les groupes de produits. Vous pouvez simplement ajouter ceci dans le ci-dessous.

La réponse compliquée/efficace peut être la suivante:

select customer 
    , max(product) keep (dense_rank first order by priority) as main_product 
    , listagg(case when priority = 2 then product end, ', ') 
     within group (order by product) as sub_product 
    from products 
group by customer 

SQL Fiddle

Par client, la colonne PRODUCT suppose que chaque client a un produit principal, puis obtient le premier produit dans l'ordre par priorité . La deuxième colonne prend seulement où la priorité est 2 et utilise la fonction de concaténation de chaîne LISTAGG() pour concaténer vos valeurs ensemble.

Je recommande vivement Rob van Wijk blog post about the KEEP clause.

Une plus standard solution SQL ressemblerait à ceci:

select a.customer, a.product as main_product 
    , listagg(b.product, ', ') within group (order by b.product) as sub_product 
    from products a 
    join products b 
    on a.customer = b.customer 
where a.priority = 1 
    and b.priority = 2 
group by a.customer, a.product 

-à-dire trouver tout ce qui a une priorité de 1, utiliser pour générer vos deux lignes, puis obtenir tout avec une priorité de 2 et de regrouper les .

+0

Une fois que je faisais ci-dessus, je suis une erreur qui dit qu'il ya une limite que vous pouvez aller. Il est environ 4K longueur. Donc, assurez-vous de ne pas dépasser la longueur totale de votre personnage. La conversion de to_clob a également des limites. ORA-01489: le résultat de la concaténation de chaîne est trop long 01489. 00000 - "le résultat de la concaténation de chaîne est trop long" * Cause: le résultat de la concaténation de chaîne est supérieur à la taille maximale. * Action: Assurez-vous que le résultat est inférieur à la taille maximale. –

-1

Essayez ceci,

select customer 
    , (select Product from yourtablename where pirority = 1) AS Main_Product 
    , (select wm_concat(Product) from yourTablename where pirority = 2) AS Sub_product  
    from yourtablename 
group by customer 
+1

Pourquoi utiliseriez-vous une fonction non documentée WM_CONCAT() quand LISTAGG() existe dans 11g (que l'OP utilise)? Vous accédez également à une table 3 fois ici ... Comme votre premier accès ne sélectionne qu'une seule ligne par client, vous pouvez le faire à la place: http://www.sqlfiddle.com/#!4/52137/4. supprime l'un des scans. – Ben

+0

Ben j'ai testé. Son fonctionnement lorsque le type de données varchar2 ne fonctionne pas avec le type de données nvarchar2 – Milton

+0

Qu'est-ce que cela signifie @Milton? Vous avez testé la réponse? Ça va certainement marcher ... Ou avez-vous testé autre chose? – Ben