Search code examples
sqlhanahana-sql-script

How to aggregate values from different rows in sql (HANA)?


I have a table of shipments defined like so (the table is stored in a HANA database, if relevant):

CREATE COLUMN TABLE SHIPMENTS (
    ShipmentID INT PRIMARY KEY,
    Received INT,
    Facility NVARCHAR(10),
    Item NVARCHAR(20)
);

Here, the 'Received' column denotes the point in time at which each shipment is received, Facility is where the shipment is received and Item is the content of the shipment.

I have filled it with data like so:

INSERT INTO SHIPMENTS VALUES (1, 0, 'Factory', 'Production machine');
INSERT INTO SHIPMENTS VALUES (2, 0, 'Office', 'Printer');
INSERT INTO SHIPMENTS VALUES (3, 0, 'Factory', 'Coffee maker');
INSERT INTO SHIPMENTS VALUES (4, 1, 'Office', 'Coffee maker');
INSERT INTO SHIPMENTS VALUES (5, 1, 'Factory', 'Fax Machine');
INSERT INTO SHIPMENTS VALUES (6, 2, 'Office', 'Computers');
INSERT INTO SHIPMENTS VALUES (7, 2, 'Factory', 'Fridge');
INSERT INTO SHIPMENTS VALUES (8, 2, 'Factory', 'Freezer');
INSERT INTO SHIPMENTS VALUES (9, 2, 'Office', 'Fax Machine');

I would like to query the database to find, at each point in time, which items have been received up until that point. Based on an answer from another thread, I start by doing this:

SELECT Facility, Received, STRING_AGG (Item, ';') as Items
    FROM (
        SELECT * FROM SHIPMENTS 
        ORDER BY Facility, Received
    )
GROUP BY Facility, Received
ORDER BY Facility, Received;

which results in

  | FACILITY | RECEIVED | ITEMS
---------------------------------------------------------
1 | Factory  | 0        | Production Machine;Coffee maker
2 | Factory  | 1        | Fax Machine
3 | Factory  | 2        | Fridge;Freezer
4 | Office   | 0        | Printer
5 | Office   | 1        | Coffee maker
6 | Office   | 2        | Computers;Fax Machine

However, I would like this

  | FACILITY | RECEIVED | ITEMS
---------------------------------------------------------
1 | Factory  | 0        | Production Machine;Coffee maker
2 | Factory  | 1        | Production Machine;Coffee maker;Fax Machine
3 | Factory  | 2        | Production Machine;Coffee maker;Fax Machine;Fridge;Freezer
4 | Office   | 0        | Printer
5 | Office   | 1        | Printer;Coffee maker
6 | Office   | 2        | Printer;Coffee maker;Computers;Fax Machine

I.e, each row displays what is received at that point, and everything that has already been received. Is there a nice way to do this in SQL?


Solution

  • You can try using a correlated query in the select clause to generate the csv data you want:

    SELECT
        Facility,
        Received,
        (SELECT STRING_AGG (s2.Item, ';') FROM SHIPMENTS s2
         WHERE s2.Facility = s1.Facility AND s2.Received <= s1.Received
         GROUP BY s2.Facility) AS ITEMS
    FROM SHIPMENTS s1
    GROUP BY
        Facility,
        Received
    ORDER BY
        Facility;