SQL: автоматически заполнять цену между датами - PullRequest
2 голосов
/ 25 февраля 2020

Я пытаюсь написать представление из двух таблиц: одна ссылочная таблица содержит идентификатор продукта и недели:

+------------+------+
| Product_id | week |   t1
+------------+------+
|          1 |    1 |
|          2 |    1 |
|          1 |    2 |
|          2 |    2 |
|          1 |    3 |
|          2 |    3 |
+------------+------+ etc...

другая содержит идентификатор продукта, недели, когда цена продукта изменилась, и цена

+------------+------+-------+
| Product_id | week | price | t2
+------------+------+-------+
|          1 |    1 |    70 |
|          1 |    2 |    50 |
|          2 |    2 |    70 |
|          1 |    4 |    30 |
|          2 |    4 |    40 |
+------------+------+-------+

Я знаю, как этого легко достичь, объединив две таблицы:

+------------+------+-------+
| Product_id | week | price | 
+------------+------+-------+
|          1 |    1 |    70 |
|          1 |    2 |    50 |
|          1 |    3 |       |
|          1 |    4 |    30 |
|          1 |    5 |       |
|          2 |    1 |       |
|          2 |    2 |    70 |
|          2 |    3 |       |
|          2 |    4 |    40 |
|          2 |    5 |       |
+------------+------+-------+

Но мои цели скорее заключаются в том, чтобы заполнить пробелы и получить цену за каждую неделю ( без создания новой таблицы), например:

+------------+------+-------+
| Product_id | week | price |
+------------+------+-------+
|          1 |    1 |    70 |
|          1 |    2 |    50 |
|          1 |    3 |    50 |
|          1 |    4 |    30 |
|          1 |    5 |    30 |
|          2 |    1 |       |
|          2 |    2 |    70 |
|          2 |    3 |    70 |
|          2 |    4 |    40 |
|          2 |    5 |    40 |
+------------+------+-------+ (product 2 isn't sold yet at week 1, so it doesn't have a price).

Я не вижу, как бы я это сделал в SQL. Я еще не использовал PARTITION BY или LAG, и это может быть то, что я ищу. Если кто-нибудь может направить меня в правильном направлении, я был бы признателен:)

Ответы [ 3 ]

1 голос
/ 25 февраля 2020

Вы можете использовать оконные функции - здесь пригодится предложение ignore nulls, которое поддерживает teradata:

select
    t1.product_id,
    t1.week,
    coalesce(
        t2.price,
        lag(t2.price ignore nulls) over(partition by t1.product_id order by t1.week)
    ) price
from t1
left join t2 
    on  t2.product_id = t1.product_id
    and t2.week = t1.week

Или еще лучше, как рекомендует dnoeth, вы можете использовать last_value(), что позволяет избежать потребность в coalesce():

select
    t1.product_id,
    t1.week,
    last_value(t2.price ignore nulls) over(partition by t1.product_id order by t1.week) price
from t1
left join t2 
    on  t2.product_id = t1.product_id
    and t2.week = t1.week
0 голосов
/ 25 февраля 2020

Вы можете сделать это с помощью LEFT JOIN.

SELECT t1.Product_id, t1.week, tmp.price
FROM t1
LEFT JOIN t2 tmp ON tmp.Product_id = t1.Product_id AND
                    tmp.week = (SELECT MAX(week) FROM t2
                                WHERE Product_id = tmp.Product_id AND week <= t1.week)
ORDER BY t1.Product_id, t1.week

. Я бы сказал, что это все же чище с OUTER APPLY, но я не знаю, поддерживается ли это teradata.

SELECT t1.Product_id, t1.week, oa.price
FROM t1
OUTER APPLY (SELECT TOP 1 price FROM t2
             WHERE Product_id = t1.Product_id AND week <= t1.week
             ORDER BY week DESC) oa
ORDER BY t1.Product_id, t1.week
0 голосов
/ 25 февраля 2020

Используйте cross join для генерации строк, затем left join и оконные функции:

with weeks as (
      select row_number() over (order by product_id) as n
      from table1
     )
select t1.product_id, w.n as week,
       coalesce(t2.price, lag(t2.price ignore nulls) over (partition by p.product_id order by w.n)
               ) as price
from (select distinct product_id
      from table1 t1
     ) p cross join
     weeks w left join
     table2 t2
     on t2.product_id = p.product_id and t2.week = w.week
where w.n <= 5
...