У меня есть образец таблицы SQL со следующими образцами данных:

Step  |  Member
---------------
 100  |  A
 100  |  B
 200  |  C
 200  |  A
 500  |  C
 500  |  A
 500  |  D
 800  |  D
 800  |  B

Мне бы потребовалось, чтобы пользователи удалили со всех следующих последовательных шагов. Как видно из приведенной выше таблицы:

  • член A находится в последовательных шагах 100, 200 и 500, и его необходимо удалить из 200 и 500.
  • То же самое касается члена C - удален из 500, а D удален из 800.
  • Но пользователь B должен оставаться в 100 и 800, потому что они не идут подряд.

Конечный результат будет примерно таким:

Step  |  Member
---------------
 100  |  A
 100  |  B
 200  |  C
 500  |  D
 800  |  B

Есть ли способ сделать это с помощью запроса SQL?

1
Gomiunik 28 Окт 2015 в 22:57

2 ответа

Лучший ответ

Попробуй это:

;with cte as(select *,
               dense_rank() over(order by step) dr,
               row_number() over(partition by member order by step) rn 
            from t)
select member, min(step) as step
from cte
group by member, dr - rn

Идея:

Step  |  Member  | dr  |  rn  |  dr - rn
----------------------------------------
 100  |  A          1      1       0
 100  |  B          1      1       0
 200  |  C          2      1       1
 200  |  A          2      2       0
 500  |  C          3      2       1
 500  |  A          3      3       0
 500  |  D          3      1       2
 800  |  D          4      2       2
 800  |  B          4      2       2

Думаю, группировка по последнему столбцу и члену дает желаемый результат. Не могу сейчас проверить скрипку.

Поиграйте здесь http://sqlfiddle.com/#!6/c87a2/3

3
Giorgi Nakeuri 28 Окт 2015 в 21:08

После того, как я поигрался и посмотрел на похожие проблемы, вот и я.

SELECT step, member
FROM (
    SELECT s1.step, s1.member,
        (SELECT MAX(step) FROM @steps WHERE step < s1.step) as prevStep,
        (SELECT MAX(step) FROM @steps WHERE step < s1.step AND member = s1.member) as memberPrevStep
    FROM @steps as s1
) AS s2
WHERE memberPrevStep IS NULL OR prevStep <> memberPrevStep

Может ли это быть приемлемым решением или есть способ лучше?

1
Gomiunik 28 Окт 2015 в 20:18