#sql #google-bigquery #sql-insert #where-clause #window-functions
#sql #google-bigquery #sql-вставить #where-предложение #окно-функции
Вопрос:
В настоящее время я пытаюсь выяснить, как я могу условно вставить строку на основе предыдущей строки. Я довольно привык использовать оконные функции, и я полагаю, что мне придется сделать это, чтобы заставить это работать, но я не знаю никаких других функций, чтобы заставить это работать.
Набор данных, с которым я работаю, будет выглядеть следующим образом
И я бы хотел, чтобы это выглядело следующим образом:
Итак, по сути, я хочу добавить разрыв, который существует между датами двух строк. Если дата окончания одной строки имеет разрыв между ней и датой начала следующей строки, я хотел бы иметь возможность вставить строку между ними, в которой есть тот же товар и магазин с промежуточными датами и количеством проданных 0.
Я пытаюсь выполнить это в консоли Google BigQuery.
Комментарии:
1. вы действительно используете BigQuery? Вы приняли ответ, который не имеет шансов на выполнение в BigQuery и, таким образом, может ввести в заблуждение других пользователей, которые будут искать аналогичный вариант использования!
2. Я действительно использую BigQuery. И я должен спросить, что, по вашему мнению, я мог бы получить, задав вопрос с необходимостью, а затем приняв ответ, который на самом деле не удовлетворяет моей потребности? Нет, это не сработало, когда я использовал dateadd, но это сработало, когда я использовал date_add. В остальном, это абсолютно сработало для того, что мне было нужно, и я использую это прямо сейчас. Я пришел сюда, чтобы задать другой вопрос, который построен поверх моего использования этого. Именно так я обнаружил ваш комментарий.
Ответ №1:
Вы можете использовать union all
и lead()
:
select item, store, start, end, sold
from t
union all
select item, store, dateadd(end, interval 1 day), dateadd(next_start, interval -1 day)
from (select item, store, end, lead(start) over (partition item, store start) as next_start
from t
) t
where next_start dateadd(end, interval 1 day);
Комментарии:
1. Спасибо за это. Обычно мне не нужно выполнять функции такого типа, но это напомнило мне об использовании UNION ALL для такого типа вещей. Я ценю это. Мне нужно подумать о получении вашей книги!
Ответ №2:
Вы можете использовать оконные функции и insert ... select
синтаксис для создания «отсутствующих» строк:
insert into mytable (item, store, start, end, sold)
select
item,
store,
dateadd(end, interval 1 day),
dateadd(lead_start, interval -1 day),
0
from (
select
t.*,
lead(start) over(partition by item, store order by start) lead_start
from mytable t
) t
where lead_start > dateadd(end, interval 1 day)
Комментарии:
1. Я не использовал этот вариант только потому, что я выбрал первый ответ в попытке решить свою проблему, но, обдумав это, я чувствую, что это сработало бы так же хорошо для моей проблемы. Даже не думал делать это таким образом, и он использует те же функции. 6 из одного, полдюжины из другого.
Ответ №3:
Ниже приведен стандартный SQL BigQuery
#standardSQL
SELECT * FROM `project.dataset.table` UNION ALL
SELECT * FROM (
SELECT item, store,
DATE_ADD(`end`, INTERVAL 1 DAY) new_start,
DATE_SUB(LEAD(start) OVER(PARTITION BY item, store ORDER BY start), INTERVAL 1 DAY) new_end, 0
FROM `project.dataset.table`
)
WHERE new_start <= new_end
если применить к образцу данных из вашего вопроса — результат будет
Row item store start end sold
1 5 1 2020-01-01 2020-01-15 22
2 5 1 2020-01-16 2020-01-31 0
3 5 1 2020-02-01 2020-02-20 14
В случае, если вы хотите вставить эти «отсутствующие» строки в свою таблицу — вы должны использовать только second select — который
INSERT INTO `project.dataset.table`
SELECT * FROM (
SELECT item, store,
DATE_ADD(`end`, INTERVAL 1 DAY) new_start,
DATE_SUB(LEAD(start) OVER(PARTITION BY item, store ORDER BY start), INTERVAL 1 DAY) new_end, 0
FROM `project.dataset.table`
)
WHERE new_start <= new_end
Комментарии:
1. То же, что и мой комментарий к следующему ответу; Я тоже вижу, как это сработало бы, но я выбрал ответ в качестве того, который я выбрал для первой попытки (который был первым ответом). Спасибо, что тоже оставили ответ!
2. дело не в том, кто первый! важнее, какой ответ правильный и из тех, что лучше других! но, по крайней мере, исправьте! очевидно, что вам решать, какой ответ принять, но вы вводите в заблуждение других пользователей, которые будут искать похожие варианты использования
3. Ну, я полагаю, я не квалифицирован, чтобы ответить, что лучше. Что я имел в виду своим комментарием, так это то, что я вижу, насколько ваш ответ правильный, но первый ответ также был правильным. Они оба решили бы мою проблему. Итак, я приму участие в том, как мне, возможно, следует решить, что лучше. Учитывая мой уровень новичка в SQL, я не понимаю, как я мог бы сказать, какой из приведенных здесь ответов лучше другого.
4. конечно. не волнуйтесь : o) вы все сделали правильно : o) вам действительно решать, что принять, за что проголосовать и т.д.