2016-02-28 3 views
3

У меня есть следующие данные:Как ignorre же последовательные записи из группы с SQL

ItemID | ProdID | ItemTypeID 
=======+========+=========== 
1001 | 100 | A 
1002 | 100 | B 
1003 | 100 | A 
1004 | 100 | B 
1005 | 100 | B <- successive itemtype (should be excluded) 
1006 | 100 | C 
1007 | 200 | C 
1008 | 200 | A 

и я хочу перечислить ItemTypeIDs (LISTAGG) в каждой группе, но без тех же самых последовательных идентификаторов. Поэтому мой результат должен быть таким:

ProdID | ItemTypes 
=======+========== 
100 | A,B,A,B,C <- not A,B,A,B,B,C (successive B) 
200 | C,A 

ответ

1

Это сложно. 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; 
+0

Не могли бы вы дать небольшой намек на то, где вы пришли к таким вычислениям на результат работы окон? Кажется, это не решение, которое появляется через минуту. Вы должны быть опытными в таком мышлении. Мне любопытно, есть ли какая-то база знаний в отношении этого подхода. Я видел ваши ответы с такими творениями :-) –

+0

@ConsiderMe. , , Начните со второго запроса. Я думаю, что логике легче следовать. Что касается первого, просто требуется указать промежуточные результаты, чтобы увидеть, что происходит с разницей чисел строк (в моей книге «Анализ данных с использованием SQL и Excel» есть пример). –

+0

Спасибо, я обязательно проверю это. Решение с 'lag()' было первым, что пришло мне в голову. Я не придумал выражение row_number. –

Смежные вопросы