Как агрегировать значения из разных строк в sql (HANA)?

У меня есть таблица отгрузок, определенная следующим образом (таблица хранится в базе данных HANA, если это необходимо):

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

Здесь столбец «Получено» обозначает момент времени, когда была получена каждая посылка, Объект — место получения посылки, а Товар — содержимое посылки.

Я заполнил его такими данными:

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');

Я хотел бы запросить базу данных, чтобы найти в каждый момент времени, какие элементы были получены до этого момента. Основываясь на ответе из другого потока, я начинаю с этого:

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

что приводит к

  | 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

Тем не менее, я хотел бы этого

  | 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

То есть в каждой строке отображается то, что получено на данный момент, и все, что уже получено. Есть ли хороший способ сделать это в SQL?


person Kazim    schedule 22.12.2017    source источник
comment
Что вы пробовали и какую ошибку получили?   -  person Nathaniel Flick    schedule 22.12.2017
comment
@NathanielFlick ОП на самом деле показал, что они пытались, и ошибки нет, за исключением того, что результат не тот, который хотелось бы.   -  person Tim Biegeleisen    schedule 22.12.2017
comment
@TimBiegeleisen Есть ли хороший способ сделать это в SQL? мне кажется, этот вопрос открытый и не проверенный?   -  person Nathaniel Flick    schedule 22.12.2017
comment
@NathanielFlick Это вовсе не открытый конец, ОП дал нам результат, который он хочет. Я попробовал запрос ниже, полностью непроверенный, так как я не знаю HANA. Буду ждать отзывов.   -  person Tim Biegeleisen    schedule 22.12.2017
comment
@TimBiegeleisen Достаточно честно.   -  person Nathaniel Flick    schedule 22.12.2017
comment
Почему вы использовали тег SQL Server, если хотите спросить о HANA? Продукт имеет большое значение. Например, SQL Server имеет оконные функции и может вычислять промежуточную сумму, например SUM(TicketCount) OVER (ORDER BY [Date] RANGE UNBOUNDED PRECEDING). Вероятно, вы также можете использовать его с STRING_AGG SQL Server 2017. Есть ли в HANA предложение OVER?   -  person Panagiotis Kanavos    schedule 22.12.2017
comment
@PanagiotisKanavos извините за неправильную маркировку, я новичок в sql и HANA и путаю вкусы sql. Наконец-то я получил правильный запрос (на основе (теперь удаленного (?)) ответа Тима Бигелейзена и добавлю ответ с рабочим запросом.   -  person Kazim    schedule 22.12.2017
comment
@Kazim Вы можете отредактировать мой ответ или просто опубликовать свой собственный. Если последнее, я снова убью свой ответ.   -  person Tim Biegeleisen    schedule 22.12.2017
comment
@Kazim, если вы хотите, чтобы люди, которые знают HANA, даже видели вопрос, вы должны использовать тег hana. Тысячи новых вопросов в минуту. На главной странице отображаются вопросы, основанные на любимых тегах читателя.   -  person Panagiotis Kanavos    schedule 22.12.2017
comment
@PanagiotisKanavos Он дал тег Hana ... Я предположил, что это был вопрос Hana, а не SQL Server, но да, было странно видеть эти два тега вместе.   -  person Tim Biegeleisen    schedule 22.12.2017
comment
@TimBiegeleisen Я добавил тег HANA и удалил sql-server. Как я уже сказал, главная страница фильтрует вопросы. Я показываю этот вопрос только потому, что в моих любимых тегах есть sql-server и sql. Тот, у кого есть hana, не увидит этого.   -  person Panagiotis Kanavos    schedule 22.12.2017
comment
@PanagiotisKanavos Достаточно честно ... да, я обычно вижу, как вы останавливаетесь на стороне Microsoft :-)   -  person Tim Biegeleisen    schedule 22.12.2017


Ответы (2)


Вы можете попробовать использовать коррелированный запрос в предложении select для создания нужных данных csv:

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;
person Tim Biegeleisen    schedule 22.12.2017
comment
Делая это, я получаю сообщение об ошибке: correlated subquery cannot have TOP or ORDER BY. Просто для проверки я удаляю ORDER BY s2.Received, что дает мне следующую ошибку: single-row query returns more than one row. Любые идеи? - person Kazim; 22.12.2017
comment
@Kazim Попробуйте использовать GROUP BY s1.Received в подзапросе и удалите там предложение ORDER BY (что, похоже, вы уже сделали). - person Tim Biegeleisen; 22.12.2017
comment
на самом деле это произвело то же самое, что и попытка, которую я сделал в OP, за исключением того, что не было заказано Facility. - person Kazim; 22.12.2017
comment
@Kazim Моя последняя попытка: GROUP BY s2.Facility ... это может иметь смысл, потому что нам нужна одна строка CSV для каждого объекта в квитанциях. Кстати, я никогда не использовал HANA, поэтому не могу проверить этот ответ. - person Tim Biegeleisen; 22.12.2017
comment
Ваша логика кажется мне здравой, но, к сожалению, результат точно такой же, как и в ОП. - person Kazim; 22.12.2017
comment
Я думаю, проблема в том, как работает STRING_AGG... он ведет себя не так, как мы ожидали. Удаление этого ответа... - person Tim Biegeleisen; 22.12.2017
comment
Мне удалось заставить его работать так, как хотелось. Я только что изменил s1.Items (внутри STRING_AGG) на s2.items и с GROUP BY s2.Facility внутри подзапроса. Чтобы получить желаемый результат, я также добавил ORDER BY Facility в самый конец. Спасибо за помощь. - person Kazim; 22.12.2017

Возможно, было бы неплохо использовать предложение ORDER BY с функцией String_Agg, чтобы убедиться, что конкатенация будет в желаемом порядке.

select 
distinct Facility, Received,
(
    select string_agg(s.Item, ';' order by Received, ShipmentID) 
    from Shipments s 
    where 
        s.Facility = t.Facility and
        s.Received <= t.Received
    ) as Items
from Shipments t
person Eralper    schedule 22.12.2017