Как найти первую дату в массиве по каждому ID MS SQL
Всем добрый вечер!
Подскажите, как найти первую дату по такому условию (нужно вычислять для каждого уникального ID): --> Если все даты в поле "Дата оплаты" < "Дата заказа", то "Дата заказа" --> Если есть "дата заказа" > "Дата оплаты", то выбрать наименьшую "Дата заказа", которая > "Дата оплаты"
На скриншоте пример данных запроса по 2-м ID. В 4-м столбце (выделен оранжевой рамкой):
- для первого ID должна быть дата "2022-07-04 11:45:22.000"
pay.[Request_ID]
,pay.[Period] as 'Дата оплаты'
,rq.[Period] as 'Дата заказа'
,min (iif (pay.[Period]>rq.[Period],pay.[Period],rq.[Period])) over (partition by pay.[Request_ID])
,iif (pay.[Period]>rq.[Period],pay.[Period],rq.[Period])
from [dbo].[Settlement] pay
left join [dbo].[Request] rq on rq.Request_ID = pay.Request_ID
where pay.Period >='20220101'
and pay.Request_ID in (0x845500505695E8DC11ECFB6FF62DAF06,0x845800505695E8DC11ED455732D595C0)
group by pay.[Request_ID],pay.[Period],rq.[Period],iif (pay.[Period]>rq.[Period],pay.[Period],rq.[Period])````
[1]: https://i.stack.imgur.com/idlFW.png
Ответы (3 шт):
Автор решения: versetty777
→ Ссылка
SELECT
pay.[Request_ID],
MIN(CASE
WHEN pay.[Period] < rq.[Period] THEN rq.[Period]
WHEN pay.[Period] > rq.[Period] THEN MIN(CASE
WHEN rq.[Period] > pay.[Period] THEN rq.[Period]
END) OVER (PARTITION BY pay.[Request_ID])
END) AS 'Первая дата'
FROM [dbo].[Settlement] pay
LEFT JOIN [dbo].[Request] rq ON rq.Request_ID = pay.Request_ID
WHERE pay.Period >= '20220101'
AND pay.Request_ID IN (0x845500505695E8DC11ECFB6FF62DAF06, 0x845800505695E8DC11ED455732D595C0)
GROUP BY pay.[Request_ID]
Этот запрос использует конструкцию CASE для вычисления нужной даты для каждого ID и использует MIN() чтобы выбрать наименьшую дату из найденных.
Автор решения: Anton
→ Ссылка
Вот сделал запрос, чтобы можно было запускать на проверку
select * from (
values
(0x845500505695E8DC11ECFB6FF62DAF06, '2022-06-27 09:56:50.000', '2022-07-04 11:04:44.000', '2022-07-04 11:45:22.000'),
(0x845500505695E8DC11ECFB6FF62DAF06, '2022-07-04 11:45:22.000', '2022-07-04 11:04:44.000', '2022-07-04 11:45:22.000'),
(0x845500505695E8DC11ECFB6FF62DAF06, '2022-07-04 23:59:59.000', '2022-07-04 11:04:44.000', '2022-07-04 11:45:22.000'),
(0x845800505695E8DC11ED455732D595C0, '2022-10-03 11:32:55.000', '2022-10-06 12:13:54.000', '2022-10-06 15:16:26.000'),
(0x845800505695E8DC11ED455732D595C0, '2022-10-06 10:58:20.000', '2022-10-06 12:13:54.000', '2022-10-06 15:16:26.000'),
(0x845800505695E8DC11ED455732D595C0, '2022-10-06 15:16:26.000', '2022-10-06 12:13:54.000', '2022-10-06 15:16:26.000'),
(0x845800505695E8DC11ED455732D595C0, '2022-10-06 18:02:45.000', '2022-10-06 12:13:54.000', '2022-10-06 15:16:26.000'),
(0x845800505695E8DC11ED455732D595C0, '2022-10-06 23:59:59.000', '2022-10-06 12:13:54.000', '2022-10-06 15:16:26.000')
) as a ([Request_ID], [Дата оплаты], [Дата заказа], [Так должно получиться])
)
select
[Request_ID]
,[Дата оплаты]
,[Дата заказа]
,min (iif ([Дата оплаты]>[Дата заказа],[Дата оплаты],[Дата заказа])) over (partition by [Request_ID] order by [Request_ID],[Дата оплаты]) as 'Вариант1 (не верный)'
,iif ([Дата оплаты]>[Дата заказа],[Дата оплаты],[Дата заказа]) as 'Вариант2 (не верный)'
,[Так должно получиться]
from cte
group by [Request_ID],[Дата оплаты],[Дата заказа],iif ([Дата оплаты]>[Дата заказа],[Дата оплаты],[Дата заказа]),[Так должно получиться]```
Автор решения: Anton
→ Ссылка
Вот написал правильный результат, может кому пригодится :)
with cte as (
select * from (
values
(0x845500505695E8DC11ECFB6FF62DAF06, '2022-06-27 09:56:50.000', '2022-07-04 11:04:44.000', '2022-07-04 11:45:22.000'),
(0x845500505695E8DC11ECFB6FF62DAF06, '2022-07-04 11:45:22.000', '2022-07-04 11:04:44.000', '2022-07-04 11:45:22.000'),
(0x845500505695E8DC11ECFB6FF62DAF06, '2022-07-04 23:59:59.000', '2022-07-04 11:04:44.000', '2022-07-04 11:45:22.000'),
(0x845800505695E8DC11ED455732D595C0, '2022-10-03 11:32:55.000', '2022-10-06 12:13:54.000', '2022-10-06 15:16:26.000'),
(0x845800505695E8DC11ED455732D595C0, '2022-10-06 10:58:20.000', '2022-10-06 12:13:54.000', '2022-10-06 15:16:26.000'),
(0x845800505695E8DC11ED455732D595C0, '2022-10-06 15:16:26.000', '2022-10-06 12:13:54.000', '2022-10-06 15:16:26.000'),
(0x845800505695E8DC11ED455732D595C0, '2022-10-06 18:02:45.000', '2022-10-06 12:13:54.000', '2022-10-06 15:16:26.000'),
(0x845800505695E8DC11ED455732D595C0, '2022-10-06 23:59:59.000', '2022-10-06 12:13:54.000', '2022-10-06 15:16:26.000'),
(0x845800505695E8DC11ED455732D595C1, '2022-10-02 18:02:45.000', '2022-10-06 12:13:54.000', '2022-10-06 12:13:54.000')
) as a ([ID], [Дата оплаты], [Дата заказа], [Так должно получиться])
)
-- Если все даты оплаты по каждому ID меньше чем дата заказа, то берем дату заказа
-- Если есть даты оплаты больше даты заказа, то берем первую (минимальную) дату оплаты после заказа
,[cte_min] as
(
select
[ID]
,[Дата оплаты] = min([Дата оплаты])
from cte
where [Дата оплаты] > [Дата заказа]
group by [ID]
)
select
c.[ID]
,c.[Дата оплаты]
,c.[Дата заказа]
,c.[Так должно получиться]
,[Так должно получиться2] = isnull(m.[Дата оплаты],c.[Дата заказа])
from cte c
left join [cte_min] m
on m.ID = c.ID