我有一个与此类似的数据集:
身份证 | 时间戳 | 值1 | 值2 |
---|---|---|---|
1 | 2023-03-01 05:00:00 世界标准时间 | 1200 | 3.2 |
1 | 2023-03-15 05:00:00 世界标准时间 | 1400 | 2.4 |
1 | 2023-03-31 05:00:00 世界标准时间 | 2000 | 2.8 |
2 | 2023-03-01 05:00:00 世界标准时间 | 850 | 4 |
2 | 2023-03-15 05:00:00 世界标准时间 | 1250 | 4.1 |
2 | 2023-03-31 05:00:00 世界标准时间 | 3300 | 3.6 |
其中
Value 1
和Value 2
每个ID
每天同一时间服用一次。
Value 1
整个月的数量都在增加,而 Value 2
则没有。
我想找出每个
Value 1
每月最后一天和第一天 ID
的差异。
此外,我想找到每个
Value 2
每个月的最大值ID
。
为每个值列创建两个单独的查询会更容易吗?或者有没有办法在同一个查询中完成每个任务?
假设您的桌子名称是
Table
。
首先创建一个 CTE
ProcessedInfo
,以及一些额外的列以使我们的计算更容易,为此我们将使用窗口函数。
新增三个栏目如下:
Value1_FirstDay_Month
- 每年每月第一天的 Value1 值。为此,将使用 FIRST_VALUE
并按年和月分区,然后按时间戳升序排列Value1_LastDay_Month
- 与上述相同,不同之处在于它是每月和每年最后一天的 Value1。对于这一列,我们将使用 LAST_VALUE
,其分区和顺序与上一列相同。Value2_Max_ID_Month
- 每个 ID、年份和月份的最大值 2。然后,第二个 CTE
FinalResult
,我们使用第一个 CTE 中创建的列来计算所需的结果。
Value1_Diff
- Value1_LastDay_Month
和 Value1_FirstDay_Month
Value2_Max_ID_Month
- 与上面相同。无需计算,因为这是期望的结果。WITH ProcessedInfo AS (
SELECT
*,
FIRST_VALUE(Value1) OVER(PARTITION BY EXTRACT(YEAR FROM Timestamp), EXTRACT(MONTH FROM Timestamp) ORDER BY Timestamp ASC) AS Value1_FirstDay_Month,
LAST_VALUE(Value1) OVER(PARTITION BY EXTRACT(YEAR FROM Timestamp), EXTRACT(MONTH FROM Timestamp) ORDER BY Timestamp ASC) AS Value1_LastDay_Month,
MAX(Value2) OVER(PARTITION BY ID, EXTRACT(YEAR FROM Timestamp), EXTRACT(MONTH FROM Timestamp)) AS Value2_Max_ID_Month
FROM Table
),
FinalResult AS (
SELECT ID, Timestamp, Value1, Value2,
(Value1_LastDay_Month - Value1_FirstDay_Month) AS Value1_Diff,
Value2_Max_ID_Month
FROM ProcessedInfo
)
SELECT * FROM FinalResult;
实际上取决于您希望输出如何显示。无论如何,一个查询就可以了。
如果你想显示所有行,那么这里有一个方法:
您可以使用
window functions
为您计算这些值。在下面的示例中,您可以将 substring() 替换为所需的方法,以从 Big Query 中的时间戳中提取 YYYYMM。
select
id,
some_date,
value1,
value2,
max(value1) over (partition by id, substring(some_date, 1, 7)) -
min(value1) over (partition by id, substring(some_date, 1, 7)) as val1_diff,
max(value2) over (partition by id, substring(some_date, 1, 7)) as max_val2
from table1
但是,如果您只想在月份和 ID 级别进行聚合,则可以使用此方法(如果您选择,请再次将子字符串替换为您想要的方法)。
select
id,
substring(some_date, 1, 7) as yyyy_mm,
max(value1) - min(value1) as val1_diff,
max(value2) as max_vale
from table1
group by id, substring(some_date, 1, 7)
参见 this fiddle,虽然是 MySQL,但窗口函数也可以在 BQ 中使用。