Как найти первую дату в массиве по каждому ID MS SQL

Рейтинг: 0Ответов: 3Опубликовано: 21.01.2023

Всем добрый вечер!

Подскажите, как найти первую дату по такому условию (нужно вычислять для каждого уникального 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.sstatic.net/idlFW.png

Ответы

▲ 0
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() чтобы выбрать наименьшую дату из найденных.

▲ 0

Вот сделал запрос, чтобы можно было запускать на проверку

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 ([Дата оплаты]>[Дата заказа],[Дата оплаты],[Дата заказа]),[Так должно получиться]```
▲ 0

Вот написал правильный результат, может кому пригодится :)

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