【发布时间】:2019-11-29 15:21:30
【问题描述】:
我有一张如下所示的表格:
使用 SQL 中的 LAG 函数,我想仅对 star_date=end_date 的值执行 LAG,并获取过去的 start_date 记录,其中 start_date=end_date。 我的茶几会有一个额外的列,如下所示:
我希望我的问题很清楚,感谢任何帮助。
【问题讨论】:
标签: sql google-bigquery lag skip
我有一张如下所示的表格:
使用 SQL 中的 LAG 函数,我想仅对 star_date=end_date 的值执行 LAG,并获取过去的 start_date 记录,其中 start_date=end_date。 我的茶几会有一个额外的列,如下所示:
我希望我的问题很清楚,感谢任何帮助。
【问题讨论】:
标签: sql google-bigquery lag skip
您可以为这些值分配一个组并使用它:
select t.*,
(case when start_date = end_date
then lag(start_date) over (partition by (case when start_date = end_date then 1 else 0 end) order by start_date)
end) as prev_eq_start_date
from t;
或者:
select t.*,
(case when start_date = end_date
then lag(start_date) over (partition by start_date = end_date order by start_date)
end) as prev_eq_start_date
from t;
请注意,如果您的数据很大并且大多数行的日期不同,那么您可能会遇到资源问题。在这种情况下,一个额外的、未使用的 partition by 密钥可以提供帮助:
select t.*,
(case when start_date = end_date
then lag(start_date) over (partition by (case when start_date = end_date then 1 else 2 end), (case when start_date <> end_date then start_date end) order by start_date)
end) as prev_eq_start_date
from t;
这对结果没有影响,但可以避免由于不同值的行太多而导致资源错误。
【讨论】:
partition by (StartDate = EndDate)会报语法错误!
countif(),以至于我忘记了 BQ 不会将布尔值视为与其他类型相同。
partition by (StartDate = EndDate) 会完美运行!你有没有测试并确认它没有?!
partition by (start_date = end_date)),它对我来说非常有效(BigQuery 标准 SQL) - 我认为它足够优雅,可以放弃它:o(显然认为我更喜欢我的回答:o)
以下是 BigQuery 标准 SQL
#standardSQL
SELECT *, NULL AS lag_result
FROM `project.dataset.table` WHERE start_date != end_date
UNION ALL
SELECT *, LAG(start_date) OVER(ORDER BY start_date)
FROM `project.dataset.table` WHERE start_date = end_date
如果应用于您问题中的样本数据 - 结果是
Row user_id start_date end_date lag_result
1 1 2019-01-01 2019-02-28 null
2 3 2019-02-27 2019-02-28 null
3 4 2019-08-04 2019-09-01 null
4 2 2019-02-01 2019-02-01 null
5 5 2019-08-07 2019-08-07 2019-02-01
6 6 2019-08-27 2019-08-27 2019-08-07
顺便说一句,如果您的 start_date 和 end_date 是 STRING 数据类型('27/02/2019')与 DATE 类型(上面查询中假设的'2019-02-27') - 你应该使用低于一个
#standardSQL
SELECT *, NULL AS lag_result
FROM `project.dataset.table` WHERE start_date != end_date
UNION ALL
SELECT *, LAG(start_date) OVER(ORDER BY PARSE_DATE('%d/%m/%Y', start_date))
FROM `project.dataset.table` WHERE start_date = end_date
结果
Row user_id start_date end_date lag_result
1 1 01/01/2019 28/02/2019 null
2 3 27/02/2019 28/02/2019 null
3 4 04/08/2019 01/09/2019 null
4 2 01/02/2019 01/02/2019 null
5 5 07/08/2019 07/08/2019 01/02/2019
6 6 27/08/2019 27/08/2019 07/08/2019
【讨论】:
使用JOIN
SELECT T.*,T1.LAG_Result
FROM TABLE T LEFT JOIN
(
SELECT User_Id,LAG(start_date) OVER(ORDER BY start_date) LAG_Result
FROM TABLE S
WHERE start_date = end_date
) T1 ON T.User_Id = T1.User_Id
【讨论】: