2017-05-30 2 views
1

J'essaie de limiter une de mes colonnes dans ma requête SQL qui utilise LISTAGG pour grouper uniquement les 3 premières lignes dans une seule colonne.Limiter les résultats LISTAGG dans Oracle

Par exemple:

Table 
----- 
Name Orders 
--------------- 
Joe Joe_Order1 
Joe Joe_Order2 
Joe Joe_Order3 
Joe Joe_Order4 
Joe Joe_Order5 
Joe Joe_Order6 
Mark Mark_Order1 
Mark Mark_Order2 
Mark Mark_Order3 
Mark Mark_Order4 

Avez-il retourner les éléments suivants ...

Name Recent_Orders 
----------------------------- 
Joe Joe_Order1, Joe_Order2, Joe_Order3 
Mark Mark_Order1, Mark_Order2, Mark_Order3 

Je suis en mesure de concaténer les données en utilisant listagg cependant, je ne suis pas tout à fait sûr de savoir comment limiter les résultats aux 3 premiers enregistrements.

SELECT NAME, LISTAGG(Orders, ', ') within group(order by Orders) 
    as Recent_Orders 
FROM 
    Order_table 
GROUP BY 
    NAME 

Est-ce possible avec LISTAGG? Toute aide serait grandement appréciée. Merci

Répondre

1

Vous pouvez le faire en dénombrant les lignes et en utilisant case:

SELECT NAME, 
     LISTAGG(CASE WHEN seqnum <= 3 THEN Orders END, ', ') WITHIN GROUP (ORDER BY Orders) as Recent_Orders 
FROM (SELECT o.*, ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY ?? DESC) as seqnum 
     FROM Order_table o 
    ) o 
GROUP BY NAME; 

Par défaut, LISTAGG() ne tient pas compte des valeurs NULL, donc ce fait ce que vous voulez. La colonne ?? est la colonne pour spécifier la commande. Les tables SQL représentent unordered sets; il n'y a pas de "premier trois" ou de "trois derniers" à moins qu'une colonne spécifie la commande.

1

Appliquer une row_number dans un CTE, puis appliquer la restriction dans la clause WHERE

with CTE as 
(
select row_number() over(partition by NAME order by Orders) as rn, 
     a1.* 
from Order_Table a1 
) 
SELECT NAME, LISTAGG(Orders, ', ') within group(order by Orders) 
    as Recent_Orders 
FROM 
    CTE 
WHERE 
    rn <=3 
GROUP BY 
    NAME