Google BigQuery:从 table 天得到 table 一年中的所有天数
Google BigQuery: From table of days get a table with all days of year
我有这个(样本)table:
+------------+-------------------+-----------+
| 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
结果 table 应该是:
+------------+-------------------+-----------+
| 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 |
+------------+-------------------+-----------+
...
意味着一年中的每一天都有一行,当源 table 提供实际值时,attribute
有一个值,否则null
被使用。
作为第一步,创建我想到的所有(日期+用户)排列 bigquery-public-data.utility_eu.date_greg
table,使用 CROSS JOIN
创建所有需要的行。
这里有一个要使用的示例table:
#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
进行两次连接(第一次在临时 table 中,第二次在主查询中),所以我试图了解是否可以优化。
你对如何让它发挥作用有什么建议吗?
谢谢
以下适用于 BigQuery 标准 SQL
#standardSQL
WITH users AS (
SELECT DISTINCT user
FROM `project.dataset.sample`
)
SELECT d.date, u.user, s.attribute
FROM `bigquery-public-data.utility_eu.date_greg` d
CROSS JOIN users u
LEFT JOIN `project.dataset.sample` s
ON s.date = d.date
AND s.user = u.user
WHERE d.year = 2019
附带说明 - 你真的不需要使用任何额外的日期 table 因为你可以即时生成它 - 如下例
#standardSQL
WITH users AS (
SELECT DISTINCT user
FROM `project.dataset.sample`
), dates AS (
SELECT `date`
FROM UNNEST(GENERATE_DATE_ARRAY('2019-01-01', '2019-12-31')) `date`
)
SELECT d.date, u.user, s.attribute
FROM dates d
CROSS JOIN users u
LEFT JOIN `project.dataset.sample` s
ON s.date = d.date
AND s.user = u.user
我有这个(样本)table:
+------------+-------------------+-----------+
| 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
结果 table 应该是:
+------------+-------------------+-----------+
| 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 |
+------------+-------------------+-----------+
...
意味着一年中的每一天都有一行,当源 table 提供实际值时,attribute
有一个值,否则null
被使用。
作为第一步,创建我想到的所有(日期+用户)排列 bigquery-public-data.utility_eu.date_greg
table,使用 CROSS JOIN
创建所有需要的行。
这里有一个要使用的示例table:
#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
进行两次连接(第一次在临时 table 中,第二次在主查询中),所以我试图了解是否可以优化。
你对如何让它发挥作用有什么建议吗? 谢谢
以下适用于 BigQuery 标准 SQL
#standardSQL
WITH users AS (
SELECT DISTINCT user
FROM `project.dataset.sample`
)
SELECT d.date, u.user, s.attribute
FROM `bigquery-public-data.utility_eu.date_greg` d
CROSS JOIN users u
LEFT JOIN `project.dataset.sample` s
ON s.date = d.date
AND s.user = u.user
WHERE d.year = 2019
附带说明 - 你真的不需要使用任何额外的日期 table 因为你可以即时生成它 - 如下例
#standardSQL
WITH users AS (
SELECT DISTINCT user
FROM `project.dataset.sample`
), dates AS (
SELECT `date`
FROM UNNEST(GENERATE_DATE_ARRAY('2019-01-01', '2019-12-31')) `date`
)
SELECT d.date, u.user, s.attribute
FROM dates d
CROSS JOIN users u
LEFT JOIN `project.dataset.sample` s
ON s.date = d.date
AND s.user = u.user