这个问题是关于在bigquery中移动年-周字段的值。
run_id year_week value
0001 201451 13
0001 201452 6
0001 201503 3
0003 201351 8
0003 201352 5
0003 201403 1
每周在这里的范围可以从01到53。例如,2014年的上周为201452,而2015年的上周为201553。
现在,我想将每个year_week
中每个run_id
的值移动5周。对于星期,没有值,则假定它们的值为0。例如,上面示例表的输出应如下所示:
run_id year_week value
0001 201504 13
0001 201505 6
0001 201506 0
0001 201507 0
0001 201508 3
0003 201404 8
0003 201405 5
0003 201406 0
0003 201407 0
0003 201408 1
输出的解释:在上表run_id
0001中,year_week
201504的值为13,因为在输入表中,year_week
201451的值为13是201504之前的5周。
我可以通过创建从year_week
到转换后的year_week
的映射,然后进行联接以获取输出的方式以编程方式创建表,但是我想知道是否还有其他方法可以执行只需使用sql即可。
答案 0 :(得分:3)
#standardSQL
WITH `project.dataset.table` AS (
SELECT '001' run_id, 201451 year_week, 13 value UNION ALL
SELECT '001', 201452, 6 UNION ALL
SELECT '001', 201503, 3
), weeks AS (
SELECT 100 * year + week year_week
FROM UNNEST([2013, 2014, 2015, 2016, 2017]) year,
UNNEST(GENERATE_ARRAY(1, IF(EXTRACT(ISOWEEK FROM DATE(1+year,1,1)) = 1, 52, 53))) week
), temp AS (
SELECT i.run_id, w.year_week, d.year_week week2, value
FROM weeks w
CROSS JOIN (SELECT DISTINCT run_id FROM `project.dataset.table`) i
LEFT JOIN `project.dataset.table` d
USING(year_week, run_id)
)
SELECT * FROM (
SELECT run_id, year_week,
SUM(value) OVER(win) value
FROM temp
WINDOW win AS (
PARTITION BY run_id ORDER BY year_week ROWS BETWEEN 5 PRECEDING AND 5 PRECEDING
)
)
WHERE NOT value IS NULL
ORDER BY run_id, year_week
结果为
Row run_id year_week value
1 001 201504 13
2 001 201505 6
3 001 201508 3
如果您需要“保留”零行-只需更改下面的部分
SELECT i.run_id, w.year_week, d.year_week week2, value
FROM weeks w
到
SELECT i.run_id, w.year_week, d.year_week week2, IFNULL(value, 0) value
FROM weeks w
或
SUM(value) OVER(win) value
FROM temp
到
SUM(IFNULL(value, 0)) OVER(win) value
FROM temp
答案 1 :(得分:2)
如果表中所有年份-星期都有数据,则可以执行以下操作:
-f
如果您没有年份表,那么我建议您创建一个这样的表,以便您可以进行此类操作-或更通用的日历表。