SQL: Как найти индексированную дату ближайшего совпадения из одного столбца в другой?

#sql #netezza

Вопрос:

У меня есть следующий пример таблицы, которая была сгруппирована по исходному набору данных.

Я хочу найти дату, в которой значение «plus_one» является ближайшим совпадением (первый результат выше) со столбцом «значение» в данном «отделе». Это должно быть произведено в столбце «return_dt».

Например, в первой строке 1.2 в столбце «plus_one» для отдела «Одежда» ближе всего к 1.36667 в столбце «значение», поэтому в первой строке необходимо вернуть соответствующую дату (6/19/20) в столбце «return_dt» для того же отдела.

Я знаком с оконными функциями и использую ORDER BY abs (), чтобы найти ближайшее совпадение. У меня возникли проблемы с их объединением, чтобы найти индексированную дату в одной таблице.

end_dt отдел ценность плюс один return_dt
6/30/2020 0:00 Одежда 0.2 1.2 6/19/2020
6/29/2020 0:00 Одежда 0.393333 1.393333 6/18/2020
6/28/2020 0:00 Одежда 0.393333 1.393333 6/18/2020
6/27/2020 0:00 Одежда 0.393333 1.393333 6/17/2020
6/26/2020 0:00 Одежда 0.573333 1.573333 6/17/2020
6/25/2020 0:00 Одежда 0.726667 1.726667 6/16/2020
6/24/2020 0:00 Одежда 0.853333 1.853333 6/15/2020
6/23/2020 0:00 Одежда 1.02 2.02 6/12/2020
6/22/2020 0:00 Одежда 1.166667 2.166667 6/12/2020
6/21/2020 0:00 Одежда 1.166667 2.166667
6/20/2020 0:00 Одежда 1.166667 2.166667
6/19/2020 0:00 Одежда 1.366667 2.366667
6/18/2020 0:00 Одежда 1.5 2.5
6/17/2020 0:00 Одежда 1.713333 2.713333
6/16/2020 0:00 Одежда 1.84 2.84
6/15/2020 0:00 Одежда 1.986667 2.986667
6/14/2020 0:00 Одежда 1.986667 2.986667
6/13/2020 0:00 Одежда 1.986667 2.986667
6/12/2020 0:00 Одежда 2.24 3.24
6/30/2020 0:00 Игрушки 0.2 1.2 6/19/2020
6/29/2020 0:00 Игрушки 0.393333 1.393333 6/18/2020
6/28/2020 0:00 Игрушки 0.393333 1.393333 6/18/2020
6/27/2020 0:00 Игрушки 0.393333 1.393333 6/17/2020
6/26/2020 0:00 Игрушки 0.573333 1.573333 6/17/2020
6/25/2020 0:00 Игрушки 0.726667 1.726667 6/16/2020
6/24/2020 0:00 Игрушки 0.853333 1.853333 6/15/2020
6/23/2020 0:00 Игрушки 1.02 2.02 6/12/2020
6/22/2020 0:00 Toys 1.166667 2.166667 6/12/2020
6/21/2020 0:00 Toys 1.166667 2.166667
6/20/2020 0:00 Toys 1.166667 2.166667
6/19/2020 0:00 Toys 1.366667 2.366667
6/18/2020 0:00 Toys 1.5 2.5
6/17/2020 0:00 Toys 1.713333 2.713333
6/16/2020 0:00 Toys 1.84 2.84
6/15/2020 0:00 Toys 1.986667 2.986667
6/14/2020 0:00 Toys 1.986667 2.986667
6/13/2020 0:00 Toys 1.986667 2.986667
6/12/2020 0:00 Toys 2.24 3.24
6/30/2020 0:00 Games 0.2 1.2 6/19/2020
6/29/2020 0:00 Игры 0.393333 1.393333 6/18/2020
6/28/2020 0:00 Игры 0.393333 1.393333 6/18/2020
6/27/2020 0:00 Игры 0.393333 1.393333 6/17/2020
6/26/2020 0:00 Игры 0.573333 1.573333 6/17/2020
6/25/2020 0:00 Игры 0.726667 1.726667 6/16/2020
6/24/2020 0:00 Игры 0.853333 1.853333 6/15/2020
6/23/2020 0:00 Игры 1.02 2.02 6/12/2020
6/22/2020 0:00 Игры 1.166667 2.166667 6/12/2020
6/21/2020 0:00 Игры 1.166667 2.166667
6/20/2020 0:00 Игры 1.166667 2.166667
6/19/2020 0:00 Игры 1.366667 2.366667
6/18/2020 0:00 Игры 1.5 2.5
6/17/2020 0:00 Игры 1.713333 2.713333
6/16/2020 0:00 Игры 1.84 2.84
6/15/2020 0:00 Игры 1.986667 2.986667
6/14/2020 0:00 Игры 1.986667 2.986667
6/13/2020 0:00 Игры 1.986667 2.986667
6/12/2020 0:00 Игры 2.24 3.24

Я попробовал коррелированный запрос, такой как

 select t.*,
      (select t2.end_dt
       from t t2
       where t2.value > t.plus_one
       order by t2.value
       limit 1
      ) as return_dt
from t;
 

но Netezza говорит: «ОШИБКА [HY000] ОШИБКА: (2) Эта форма коррелированного запроса не поддерживается — подумайте о переписывании».

Есть идеи, как я могу создать столбец для return_dt?

Комментарии:

1. Не забывайте, что вы можете присоединить таблицу к себе

2. @Cosmos . . . Netezza не является Postgres, поэтому я удалил тег Postgres.

3. @GordonLinoff Спасибо, я все еще учусь 🙂

Ответ №1:

Боковое соединение или коррелированный подзапрос кажутся таким простым подходом:

 select t.*,
       (select t2.end_dt
        from t t2
        where t2.dept = t.dept and
              t2.value > t.plus_one
        order by t2.value
        limit 1
       ) as return_dt
from t;
 

Это довольно болезненно (и неэффективно) писать без соответствующего подзапроса. Но …

 select t.*
from (select t.end_dt, t.dept, t.value, t.plus_one,
             tnext.end_dt as return_dt,
             row_number() over (partition by t.end_dt, t.dept, t.value, t.plus_one order by tnext.value asc) as seqnum
      from t left join
           t tnext
           on tnext.dept = t.dept and
              tnext.value > t.plus_one
     ) t
where seqnum = 1;
 

Комментарии:

1. Спасибо, это похоже на то, где мне нужно быть. Однако, похоже, это решение не работает с моим полным набором данных, который на самом деле сгруппирован по отдельному полю. Я получаю следующую ошибку от Netezza «ОШИБКА [HY000] Эта форма коррелированного запроса не поддерживается — подумайте о переписывании» Я внес изменения в вышеуказанный вопрос, чтобы включить более полное представление о ситуации, есть ли шанс, что вы могли бы помочь мне изменить?

2. @Cosmos . . . Помогает ли это, если есть условие равенства на dept ?

3. Невероятно, это работает безупречно. Большое вам спасибо!!!