Найти следующую дату после даты в столбце (SQL Server 2008) - PullRequest
0 голосов
/ 29 февраля 2020

Я пытаюсь построить запрос с 2 таблицами, Orders и Repairs. Цель состоит в том, чтобы найти первую дату ремонта после даты заказа для любого конкретного клиента с нулевым значением, если между заказами не было ремонта. Вот текущие столбцы для каждого:

CustomerID LocationID SaleDate
-------------------------------
1          1b         1/10/2019
1          1b         2/23/2019
1          1c         1/29/2019
2          2a         3/01/2019
2          2a         3/25/2019

CustomerID LocationID RepairDate
--------------------------------
1          1b         2/25/2019
1          1c         2/13/2019
1          1c         2/27/2019
2          2a         3/03/2019
2          2a         3/17/2019

Вот ожидаемый результат. Любые идеи? По какой-то причине ничего из того, что я пробовал, похоже не работает

CustomerID LocationID SaleDate  RepairDate
-------------------------------------------
1          1b         1/10/2019 null
1          1b         2/23/2019 2/25/2019
1          1c         1/29/2019 2/13/2019
2          2a         3/1/2019  3/3/2019
2          2a         3/25/2019 null

Ответы [ 2 ]

0 голосов
/ 29 февраля 2020

Это немного многословно, но мне пришло в голову лучший способ предотвратить сопоставление одного и того же ремонта со всеми предыдущими продажами, что, как я полагаю, является одной из проблем с гораздо более простым ответом Гордона Линоффа. Я объединил ваши две таблицы в один журнал событий, а затем использовал оконную функцию row_number, чтобы определить последовательности событий, влияющих на одного и того же клиента и местоположение. Попробуйте здесь

WITH eventlog
     AS (SELECT *,
                Row_number()
                  OVER(
                    partition BY customerid, locationid
                    ORDER BY eventdate) AS seq
         FROM   (SELECT customerid,
                        locationid,
                        saledate AS eventdate,
                        's'      AS type
                 FROM   orders
                 UNION
                 SELECT customerid,
                        locationid,
                        repairdate AS repairdate,
                        'r'        AS type
                 FROM   repairs) a)
SELECT s.customerid,
       s.locationid,
       s.eventdate AS saledate,
       r.eventdate AS repairdate
FROM   eventlog s
       LEFT JOIN eventlog r
              ON s.seq + 1 = r.seq
                 AND s.customerid = r.customerid
                 AND s.locationid = r.locationid
                 AND r.type = 'r'
WHERE  s.type = 's';  
0 голосов
/ 29 февраля 2020

Использование outer apply:

select o.*, r.*
from orders o outer apply
     (select top (1) r.*
      from repairs r
      where r.customerId = o.customerId and
            r.locationid = o.locationid and
            r.RepairDate > o.SaleDate
      order by r.RepairDate
     ) r;

Примечание. Вы указываете, что хотите указать первую дату ремонта для клиента . Однако данные свидетельствуют о том, что вы действительно имеете в виду комбинацию клиент / местоположение.

РЕДАКТИРОВАТЬ:

Спасибо за настройку SQL Fiddle. Это проясняет проблему. Я думаю, что этот твик делает то, что вы хотите:

- Ответ от Гордона Линоффа

select o.*, r.*
from (select o.*,
             lead(saledate) over (partition by customerid order by saledate) as next_salesdate
      from orders o
     ) o outer apply
     (select top (1) r.*
      from repairs r
      where r.customerId = o.customerId and
            r.locationid = o.locationid and
            r.RepairDate > o.SaleDate and
            (r.RepairDate < o.next_salesdate or o.next_salesdate is null)
      order by r.RepairDate
     ) r;

Здесь - это db <> скрипка.

...