Гость
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Первая следующая "не такая". Можно ли решить с помощью оконных функций? / 9 сообщений из 9, страница 1 из 1
02.04.2020, 16:16
    #39943191
uaggster
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Первая следующая "не такая". Можно ли решить с помощью оконных функций?
Коллеги, приветствую!

Уже часа 2 активно туплю.
Можно ли решить "в один проход", с помощью оконной функции, следующую задачу:
Нужно каждому [i], сопоставить следующий в порядке возрастания [k] [i], в том случае если у этого следующего [i] ---- [j] > 0

Неправильный вариант решения - я привел:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Declare @t table (i int, j int, k int identity (1,1))

insert into @t (i,j)
Values (1, 1), (3, 1), (2, 1), (4, 0), (6, 1), (5, 0), (9, 0),  (7, 1), (8, 0), (10, 1), (11, 0)

Select i,
FIRST_VALUE(Case when j>0 then i  END) over (order by Case when j=0 then 1 Else 0 END ASC, k asc
Rows between 1 Following and Unbounded Following
) ii

from @t a
Order by k ASC


Он выдает:
i ii1 33 22 64 NULL6 75 NULL9 NULL7 108 NULL10 NULL11 NULL

А нужно:
i ii1 33 22 64 66 75 79 77 108 1010 NULL11 NULL

Обратите внимание, что никакое решение, кроме однопроходного оконного - мне не интересно.
Я легко могу решить этот кейс с помощью, например, самосоединения таблицы.
Интересует именно решение с помощью оконной функции!
...
Рейтинг: 0 / 0
02.04.2020, 17:15
    #39943221
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Первая следующая "не такая". Можно ли решить с помощью оконных функций?
Код: sql
1.
2.
3.
4.
5.
Select
 i,
 min(case when j > 0 then k * 1000 + i end) over (order by k rows between 1 following and unbounded following) % 1000
from @t a
Order by k ASC
...
Рейтинг: 0 / 0
02.04.2020, 17:27
    #39943226
uaggster
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Первая следующая "не такая". Можно ли решить с помощью оконных функций?
invm
Код: sql
1.
2.
3.
4.
5.
Select
 i,
 min(case when j > 0 then k * 1000 + i end) over (order by k rows between 1 following and unbounded following) % 1000
from @t a
Order by k ASC


Гыыы, какой грязный трюк! invm, спасибо.
В оригинале i - guid, но сейчас гляну, что можно сделать!
Спасибо. :-)
...
Рейтинг: 0 / 0
02.04.2020, 17:57
    #39943241
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Первая следующая "не такая". Можно ли решить с помощью оконных функций?
uaggster
В оригинале i - guid
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Declare @t table (i int, j int, k int identity (1,1), g uniqueidentifier default newid())

insert into @t (i,j)
Values (1, 1), (3, 1), (2, 1), (4, 0), (6, 1), (5, 0), (9, 0),  (7, 1), (8, 0), (10, 1), (11, 0)

Select
 i, g,
 min(case when j > 0 then k * 1000 + i end) over (order by k rows between 1 following and unbounded following) % 1000,
 cast(substring(min(case when j > 0 then str(k, 10) + cast(g as varchar(36)) end) over (order by k rows between 1 following and unbounded following), 11, 100000) as uniqueidentifier)
from @t a
Order by k ASC
...
Рейтинг: 0 / 0
02.04.2020, 19:20
    #39943275
uaggster
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Первая следующая "не такая". Можно ли решить с помощью оконных функций?
invm, Да, спасибо, примерно так и сделал.
...
Рейтинг: 0 / 0
03.04.2020, 00:19
    #39943341
nullin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Первая следующая "не такая". Можно ли решить с помощью оконных функций?
uaggster, как-то такое сделал без конкатенаций в несколько уровней оконок. Пишу, как любитель оконных функций

Кмк, в примере выше, stuff() был бы по изящнее, хотя насчет переносимости не уверен.
...
Рейтинг: 0 / 0
03.04.2020, 00:54
    #39943346
nullin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Первая следующая "не такая". Можно ли решить с помощью оконных функций?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
Declare @t table (i int, j int, k int identity (1,1), g uniqueidentifier default newid())

insert into @t (i,j)
Values (0, 0), (7, 0), (8, 1), (3, 1), (7, 1), (4, 0), (6, 1), (5, 0), (9, 0),  (5, 1), (8, 0), (10, 1), (11, 0), (0, 1)

select i, j, k, s
     , v
     , max(v) over(partition by s) as iRes
     , g
     , max(lg) over(partition by s) as gRes
from (select i, g, j, k
           , sum(j) over(order by k) as s
           , iif(1 = lead(j) over(order by k), lead(i) over(order by k), null) as v
           , iif(1 = lead(j) over(order by k), lead(g) over(order by k), null) as lg
      from @t a) as b


fiddle
...
Рейтинг: 0 / 0
03.04.2020, 09:19
    #39943385
uaggster
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Первая следующая "не такая". Можно ли решить с помощью оконных функций?
nullin, Блин, это даже не раскуришь с наскока.
Нет, запрос invm мне больше нравится (на первый взгляд). Реальный запрос на реальной базе на 15 миллионах записей считался всего около 10 минут. И да, со stuff. Присобачиваю спереди значение поля, по которому производится сортировка (datatime), а потом усекаю как stuff(..., 1, 19, '')
...
Рейтинг: 0 / 0
03.04.2020, 13:58
    #39943500
nullin
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Первая следующая "не такая". Можно ли решить с помощью оконных функций?
uaggster, план этого запроса по сравнению с запросом от invm может ужаснуть
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Первая следующая "не такая". Можно ли решить с помощью оконных функций? / 9 сообщений из 9, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]