Это сложно. Listagg()
даже не разрешает distinct
, поэтому вся работа должна выполняться в подзапросах.
Вы можете определить последовательный код ItemTypeId
, используя разницу в методах номеров рядов. Затем, когда группы определены, можно объединить по группам и затем сделать listagg()
:
select ProdId,
listagg(ItemId, ',') within group (order by seqnum) as items
from (select ProdId, ItemId, count(*) as NumItems,
row_number() over (partition by ProdId order by min(ItemId)) as seqnum
from (select t.*,
(row_number() over (partition by ProdId order by ItemId) -
row_number() over (partition by ProdId, ItemTypeId order by ItemId)
) as grp
from t
) t
group by ProdId, ItemTypeId, grp
) t
group by ProdId;
EDIT:
Другим способом подойти к этому использует lag()
, чтобы найти, где начинаются новые группы. Предыдущий метод позволяет получить счетчик. Этот метод может быть проще понять:
select ProdId,
listagg(ItemId, ',') within group (order by ItemId) as items
from (select t.*
from (select t.*,
lag(ItemTypeId) over (partition by ProdId order by ItemId) as prev_ItemTypeId
from t
) t
where prev_ItemTypeId is null or prev_ItemTypeId <> ItemTypeId
) t
group by ProdId;
Не могли бы вы дать небольшой намек на то, где вы пришли к таким вычислениям на результат работы окон? Кажется, это не решение, которое появляется через минуту. Вы должны быть опытными в таком мышлении. Мне любопытно, есть ли какая-то база знаний в отношении этого подхода. Я видел ваши ответы с такими творениями :-) –
@ConsiderMe. , , Начните со второго запроса. Я думаю, что логике легче следовать. Что касается первого, просто требуется указать промежуточные результаты, чтобы увидеть, что происходит с разницей чисел строк (в моей книге «Анализ данных с использованием SQL и Excel» есть пример). –
Спасибо, я обязательно проверю это. Решение с 'lag()' было первым, что пришло мне в голову. Я не придумал выражение row_number. –