У меня есть эта (примерная) таблица:
+------------+-------------------+-----------+
| Date | User | Attribute |
+------------+-------------------+-----------+
| 2019-01-01 | user1@example.com | apple |
| 2019-02-01 | user2@example.com | pear |
| 2019-03-01 | user1@example.com | carrot |
| 2019-03-01 | user2@example.com | orange |
+------------+-------------------+-----------+
Мне нужно создать полную перестановку всех пар (дата + пользователь), заполнив все пропущенные дни 2019 года (с attribute
какnull
).
Как и в моем примере, у меня есть 2 разных пользователя:
- user1@example.com
- user2@example.com
Результирующая таблица должна быть:
+------------+-------------------+-----------+
| Date | User | Attribute |
+------------+-------------------+-----------+
| 2019-01-01 | user1@example.com | apple |
| ... | user1@example.com | null |
| 2019-03-01 | user1@example.com | carrot |
| ... | user1@example.com | null |
| 2019-12-31 | user1@example.com | null |
| 2019-01-01 | user2@example.com | null |
| ... | user2@example.com | null |
| 2019-02-01 | user2@example.com | pear |
| ... | user2@example.com | null |
| 2019-03-01 | user2@example.com | orange |
| ... | user2@example.com | null |
| 2019-12-31 | user2@example.com | null |
+------------+-------------------+-----------+
...
подразумевает, что существует строка для каждого отдельного дня года, а attribute
имеет значение, когда исходная таблицапредоставляет фактическое значение, в противном случае используется null
.
В качестве первого шага, чтобы создать все перестановки (дата + пользователь), о которых я думал, используя таблицу bigquery-public-data.utility_eu.date_greg
, используя CROSS JOIN
, чтобы создать всенеобходимые строки.
Вот пример таблицы, которая будет использоваться:
#standardSQL
WITH sample AS (
SELECT DATE('2019-01-01') date, 'user1@example.com' user, 'apple' attribute
UNION ALL
SELECT DATE('2019-02-01'), 'user2@example.com', 'pear'
UNION ALL
SELECT DATE('2019-03-01'), 'user1@example.com', 'carrot'
UNION ALL
SELECT DATE('2019-03-01'), 'user2@example.com', 'orange'
)
И вот первый запрос, который я попытался:
SELECT d.date,s.* EXCEPT(date)
FROM sample s
CROSS JOIN `bigquery-public-data.utility_eu.date_greg` d
WHERE d.year = 2019
ORDER BY date,user
Но это слишком много, потому чтотакже значения attribute
используются внутри объединения, и я получаю значение, реплицируемое на все дни, которые не связаны с исходным.
Я думаю, что мне нужно что-то вроде DISTINCT
, чтобы получить только уникальные (дата + пользователь) пары, и только потом связывать значение attribute
, если оно есть.
Это первоеЯ нашел рабочее решение:
distinct_couples AS (
SELECT DISTINCT d.date,s.user
FROM sample s CROSS JOIN `bigquery-public-data.utility_eu.date_greg` d
WHERE d.year = 2019
)
SELECT d.*, s.attribute
FROM distinct_couples d
LEFT JOIN sample s USING(date,user)
ORDER BY date,user
Но я делаю соединение с sample
дважды (сначала в таблице временных данных, а затем в основном запросе), поэтому я пытаюсь понять, можно ли оптимизировать.
Есть ли у вас какие-либо предложения о том, как заставить это работать?Спасибо