SQL - получить запасные значения, если данные недоступны - PullRequest
1 голос
/ 08 октября 2019

У меня есть таблица TBL_A вроде:

   CLASS_ID  PERIOD_DT   MAX_DT
  -----------------------------------
   358614  2018-09-30  2018-09-30
   358614  2017-09-30  2018-09-30
   358614  2016-09-30  2018-09-30
   358614  2015-09-30  2018-09-30
   358614  2014-09-30  2018-09-30
   358614  2013-09-30  2018-09-30

и TBL_B LIKE:

    CLASS_ID  CLASS_DT   
   ----------------------
    358614  2018-09-30  
    358614  2017-09-30  
    358614  2016-09-30 

Я пытаюсь получить набор результатов с помощью CLASS_DT за последние шесть лет и некоторыеклассы не имеют достаточно информации. Если даты недоступны, мне нужно использовать предыдущие доступные данные, близкие к дате текущего периода. поэтому мой окончательный результат должен выглядеть следующим образом:

Ожидаемый результат :

 PERIOD_DT   FALLBACK_CLASS_DT
-------------------------------
 2018-09-30  2018-09-30 
 2017-09-30  2017-09-30
 2016-09-30  2016-09-30  
 2015-09-30  2016-09-30 // fallback dates, since they are not available
 2014-09-30  2016-09-30
 2013-09-30  2016-09-30          

И запрос, который я пытаюсь выполнить:

 SELECT A.PERIOD_DT,
   (SELECT TOP 1 CAST(B.CLASS_DT AS DATE)
    FROM TBL_B AS B
    WHERE B.CLASS_ID = A.CLASS_ID
      AND CAST(B.CLASS_DT AS DATE) <= CAST(A.PERIOD_DT AS DATE) 
      AND CAST(A.PERIOD_DT AS DATE) <= CAST(A.MAX_DT AS DATE)
    ORDER BY B.CLASS_DT DESC) AS FALLBACK_CLASS_DT
FROM TBL_A AS A
WHERE A.CLASS_ID = 358614  
ORDER BY A.PERIOD_DT DESC;

Результат, который я получаю:

PERIOD_DT   FALLBACK_CLASS_DT
-------------------------------
 2018-09-30  2018-09-30 
 2017-09-30  2017-09-30
 2016-09-30  2016-09-30  
 2015-09-30  NULL
 2014-09-30  NULL
 2013-09-30  NULL 

Может кто-нибудь дать мне знать, как я могу получить этот результат?

Ответы [ 2 ]

0 голосов
/ 08 октября 2019

Вот запрос, который работал для меня

  SELECT 
    A.CLASS_ID,
    A.PERIOD_DT,
    ISNULL((SELECT TOP 1 CAST(B.CLASS_DT AS DATE)
    FROM TBL_B AS B
    WHERE B.CLASS_ID = A.CLASS_ID
          AND CAST(B.CLASS_DT AS DATE) <= CAST(A.PERIOD_DT AS DATE) 
          AND CAST(A.PERIOD_DT AS DATE) <= CAST(A.MAX_DT AS DATE)
    ORDER BY B.CLASS_DT DESC
    ), B2.CLASS_DT) AS FALLBACK_CLASS_DT
FROM TBL_A AS A
LEFT JOIN (SELECT B.CLASS_ID, MIN(B.CLASS_DT) AS CLASS_DT
           FROM TBL_B AS B
           GROUP BY B.CLASS_ID) AS B2 ON B2.CLASS_ID = A.CLASS_ID
WHERE A.CLASS_ID = 358614  
ORDER BY A.PERIOD_DT DESC;
0 голосов
/ 08 октября 2019

Один метод:

select a.*, coalesce(b.class_dt, bdef.class_dt)
from tbl_a a left join
     tbl_b b
     on b.CLASS_ID = a.CLASS_ID and
        b.class_dt >= a.period_dt and
        b.class_dt <= a.max_dt left join
     (select b.class_id, min(b.period_dt) as class_dt
      from tbl_b
      group by b.class_id
     ) bdef
     on bdef.class_id = a.class_id;

Я думаю, вы также можете сделать это, используя outer apply:

select a.*, b.class_dt
from tbl_a a left join
     (select top (1) b.*
      from tbl_b b
      where b.CLASS_ID = a.CLASS_ID and
            b.class_dt <= a.max_dt 
      order by b.period_dt desc
     ) b
...