Выбирайте верхние строки, пока значение в указанном столбце c не появится дважды - PullRequest
1 голос
/ 04 мая 2020

У меня следующий запрос, в котором я пытаюсь выбрать все записи, упорядоченные по дате, пока второй раз EmailApproved = 1 не будет найден. Вторая запись, где EmailApproved = 1 не должна быть выбрана.

declare @Test table (id int, EmailApproved bit, Created datetime)

insert into @Test (id, EmailApproved, Created)
values
  (1,0,'2011-03-07 03:58:58.423')
  , (2,0,'2011-02-21 04:55:52.103')
  , (3,0,'2011-01-29 13:24:02.103')
  , (4,1,'2010-10-12 14:41:54.217')
  , (5,0,'2010-10-12 14:34:15.903')
  , (6,0,'2010-10-12 10:10:19.123')
  , (7,1,'2010-08-27 12:07:16.073')
  , (8,1,'2010-08-25 12:15:49.413')
  , (9,0,'2010-08-25 12:14:51.970')
  , (10,1,'2010-04-12 16:43:44.777')

select *
  , case when Row1 = Row2 then 1 else 0 end Row1EqualRow2
from (
  select id, EmailApproved, Created
    , row_number() over (partition by EmailApproved order by Created desc) Row1
    , row_number() over (order by Created desc) Row2
  from @Test
) X
--where Row1 = Row2
order by Created desc

, которая дает следующие результаты:

id  EmailApproved   Created                 Row1    Row2    Row1EqualsRow2
1   0               2011-03-07 03:58:58.423 1       1       1
2   0               2011-02-21 04:55:52.103 2       2       1
3   0               2011-01-29 13:24:02.103 3       3       1
4   1               2010-10-12 14:41:54.217 1       4       0
5   0               2010-10-12 14:34:15.903 4       5       0
6   0               2010-10-12 10:10:19.123 5       6       0
7   1               2010-08-27 12:07:16.073 2       7       0
8   1               2010-08-25 12:15:49.413 3       8       0
9   0               2010-08-25 12:14:51.970 6       9       0
10  1               2010-04-12 16:43:44.777 4       10      0

То, что я на самом деле хочу, это:

id  EmailApproved   Created                 Row1    Row2    Row1EqualsRow2
1   0               2011-03-07 03:58:58.423 1       1       1
2   0               2011-02-21 04:55:52.103 2       2       1
3   0               2011-01-29 13:24:02.103 3       3       1
4   1               2010-10-12 14:41:54.217 1       4       0
5   0               2010-10-12 14:34:15.903 4       5       0
6   0               2010-10-12 10:10:19.123 5       6       0

Примечание: Row, Row2 & Row1EqualsRow2 - это просто рабочие столбцы для отображения моих расчетов.

1 Ответ

2 голосов
/ 04 мая 2020

Шаги:

  1. Создайте номер строки rn по всем строкам, если id не в последовательности.
  2. Создайте номер строки, approv_rn , разделенный на EmailApproved, поэтому мы знаем, когда EmailApproved = 1 во второй раз
  3. Используйте outer apply, чтобы найти номер строки second экземпляра EmailApproved = 1
  4. In предложение where отфильтровывает все строки с номером строки >= значением, найденным на шаге 3.
  5. Если доступно 1 или 0 EmailApproved записей, то outer apply вернет ноль, в этом случае вернуть все доступные строки.
    ; with test as
    (
        select  *, 
                rn         = row_number() over (order by Created desc),
                approv_rn  = row_number() over (partition by EmailApproved 
                                                    order by Created desc)
        from    @Test
    )
    select  *
    from    test t
            outer apply
            (
                select  x.rn
                from    test x
                where   x.EmailApproved = 1
                and     x.approv_rn     = 2
            ) x
    where   t.rn    < x.rn or x.rn is null
    order by t.Created desc
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...