I'm trying to limit one of my columns in my SQL query that uses LISTAGG to only group the first 3 rows into a single column.
For instance:
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
Have it return the following...
Name   Recent_Orders
-----------------------------
Joe    Joe_Order1, Joe_Order2, Joe_Order3
Mark   Mark_Order1, Mark_Order2, Mark_Order3
I'm able to concatenate the data using listagg however, I'm not entirely sure how to limit the results to the first 3 records.
SELECT NAME, LISTAGG(Orders, ', ') within group(order by Orders)
  as Recent_Orders
FROM
  Order_table
GROUP BY
  NAME
Is this possible with LISTAGG? Any help would be greatly appreciated. Thanks
Apply a row_number in a CTE, then apply the restriction in the WHERE clause
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
                        You can do this by enumerating the rows and using 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;
By default, LISTAGG() ignores NULL values, so this does what you want.
The ?? is the column for specifying the ordering.  SQL tables represent unordered sets; there is no "first three" or "last three" unless a column specifies the ordering.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With