GROUP BY 子句
使用 GROUP BY
子句,可以根据一个或多个指定的 标签 或按指定的时间间隔对数据进行分组。GROUP BY
子句需要在 SELECT
语句中使用 聚合 函数或 选择器 函数。
语法
SELECT_clause FROM_clause [WHERE_clause] GROUP BY group_expression[, ..., group_expression_n]
- group_expression:用于标识要分组的标签或时间间隔的表达式。可以是 标签键、常量、正则表达式、通配符 (
*
) 或 函数表达式。
GROUP BY 子句行为
GROUP BY tag_key
- 按特定标签分组数据GROUP BY tag_key1, tag_key2
- 按多个标签分组数据GROUP BY *
- 按所有 标签 分组数据GROUP BY /regex/
- 按与正则表达式匹配的标签键分组数据GROUP BY time()
- 将数据分组到时间间隔(窗口)中
如果查询包含 WHERE
和 GROUP BY
,则 GROUP BY
子句必须出现在 WHERE
子句之后。
按一个或多个标签列分组数据。
以下示例使用 比特币价格示例数据。
按单个标签分组数据
SELECT MEAN(*) FROM bitcoin GROUP BY code
time | mean_price |
---|
1970-01-01T00:00:00Z | 27328.848667840004 |
time | mean_price |
---|
1970-01-01T00:00:00Z | 23441.832453919982 |
time | mean_price |
---|
1970-01-01T00:00:00Z | 28054.160950480004 |
按多个标签分组数据
SELECT MEAN(*) FROM bitcoin GROUP BY code, description
time | mean_price |
---|
1970-01-01T00:00:00Z | 27328.848667840004 |
time | mean_price |
---|
1970-01-01T00:00:00Z | 23441.832453919982 |
time | mean_price |
---|
1970-01-01T00:00:00Z | 28054.160950480004 |
按与正则表达式匹配的标签键分组数据
SELECT MEAN(*) FROM bitcoin GROUP BY /^[cd]/
time | mean_price |
---|
1970-01-01T00:00:00Z | 27328.848667840004 |
time | mean_price |
---|
1970-01-01T00:00:00Z | 23441.832453919982 |
time | mean_price |
---|
1970-01-01T00:00:00Z | 28054.160950480004 |
GROUP BY 时间
GROUP BY time()
将数据分组到指定的时间间隔(也称为“窗口”)中,并将 SELECT
子句中的 聚合 和 选择器 函数应用于每个间隔。使用 time()
函数 指定要分组的时间间隔。
SELECT_clause FROM_clause WHERE <time_range> GROUP BY time(time_interval[, offset])[, group_expression (...)] [fill(behavior)]
GROUP BY time()
间隔使用预设的四舍五入的时间边界,这些边界独立于 WHERE
子句 中的时间条件。输出数据使用窗口开始边界作为聚合时间戳。 使用 time()
函数的 offset
参数可以向前或向后移动时间边界。
GROUP BY 时间并填充空白
按时间分组时,如果查询时间范围内的窗口不包含数据,则结果会为每个空窗口返回一行,其中包含空窗口的时间戳和每个查询字段的空值。在 GROUP BY
子句的末尾使用 fill()
函数 替换空值字段值。如果未包含 FILL
子句,则默认行为为 fill(null)
。
fill()
为填充值提供以下行为
- 数值字面量:将空值替换为指定的数值字面量。
- 线性:使用现有值之间的线性插值来替换空值。
- 无:删除具有空字段值的行。
- 空值:保留空值和关联的时间戳。
- 先前值:将空值替换为最近的非空值。
有关详细示例,请参阅 fill()
文档。
GROUP BY 时间示例
以下示例使用 比特币价格示例数据。
将分组和聚合查询结果放入 1 小时窗口
SELECT
MEAN(price)
FROM bitcoin
WHERE
code = 'USD'
AND time >= '2023-05-01T00:00:00Z'
AND time < '2023-05-15T00:00:00Z'
GROUP BY time(1h)
time | 平均值 |
---|
2023-05-01T00:00:00Z | 24494.27265 |
2023-05-01T01:00:00Z | 24452.1698 |
2023-05-01T02:00:00Z | 23902.666124999996 |
2023-05-01T03:00:00Z | 23875.211349999998 |
2023-05-01T04:00:00Z | 23855.6441 |
... | ... |
按标签将分组和聚合查询结果放入 1 周间隔
SELECT
MEAN(price)
FROM bitcoin
WHERE
time >= '2023-05-01T00:00:00Z'
AND time < '2023-05-15T00:00:00Z'
GROUP BY time(1w), code
time | 平均值 |
---|
2023-04-27T00:00:00Z | 27681.21808576779 |
2023-05-04T00:00:00Z | 27829.413580354256 |
2023-05-11T00:00:00Z | 26210.24799033149 |
time | 平均值 |
---|
2023-04-27T00:00:00Z | 23744.083925842704 |
2023-05-04T00:00:00Z | 23871.201395652173 |
2023-05-11T00:00:00Z | 22482.33174723755 |
time | 平均值 |
---|
2023-04-27T00:00:00Z | 28415.88231123595 |
2023-05-04T00:00:00Z | 28568.010941384844 |
2023-05-11T00:00:00Z | 26905.87242099449 |
GROUP BY 时间和偏移
将分组和聚合查询结果放入 1 小时间隔,并将时间边界偏移 +15 分钟
SELECT
MEAN(price)
FROM bitcoin
WHERE
code = 'USD'
AND time >= '2023-05-01T00:00:00Z'
AND time < '2023-05-02T00:00:00Z'
GROUP BY time(1h, 15m)
time | 平均值 |
---|
2023-04-30T23:15:00Z | |
2023-05-01T00:15:00Z | 29313.6754 |
2023-05-01T01:15:00Z | 28932.0882 |
2023-05-01T02:15:00Z | 28596.375225000003 |
2023-05-01T03:15:00Z | 28578.915075 |
... | ... |
请注意,offset
强制第一个时间边界在查询时间范围之外,因此查询不会返回第一个间隔的结果。
将分组和聚合查询结果放入 1 小时间隔,并将时间边界偏移 -15 分钟
SELECT
MEAN(price)
FROM bitcoin
WHERE
code = 'USD'
AND time >= '2023-05-01T00:00:00Z'
AND time < '2023-05-02T00:00:00Z'
GROUP BY time(1h, -15m)
time | 平均值 |
---|
2023-04-30T23:45:00Z | 29319.9092 |
2023-05-01T00:45:00Z | 29285.3651 |
2023-05-01T01:45:00Z | 28607.202666666668 |
2023-05-01T02:45:00Z | 28576.056175 |
2023-05-01T03:45:00Z | 28566.96315 |
... | ... |
GROUP BY 时间并填充空白
将分组和聚合查询结果放入 30 分钟间隔,并用 0
填充空白
SELECT
MEAN(price)
FROM bitcoin
WHERE
code = 'USD'
AND time >= '2023-05-01T00:00:00Z'
AND time < '2023-05-01T02:00:00Z'
GROUP BY
time(30m)
fill(0)
time | 平均值 |
---|
2023-05-01T00:00:00Z | 29319.9092 |
2023-05-01T00:30:00Z | 29307.4416 |
2023-05-01T01:00:00Z | 0 |
2023-05-01T01:30:00Z | 29263.2886 |
将分组和聚合查询结果放入 30 分钟间隔,并使用线性插值填充空白
SELECT
MEAN(price)
FROM bitcoin
WHERE
code = 'USD'
AND time >= '2023-05-01T00:00:00Z'
AND time < '2023-05-01T02:00:00Z'
GROUP BY
time(30m)
fill(linear)
time | 平均值 |
---|
2023-05-01T00:00:00Z | 29319.9092 |
2023-05-01T00:30:00Z | 29307.4416 |
2023-05-01T01:00:00Z | 29285.3651 |
2023-05-01T01:30:00Z | 29263.2886 |
将分组和聚合查询结果放入 30 分钟间隔,并使用先前值填充空白
SELECT
MEAN(price)
FROM bitcoin
WHERE
code = 'USD'
AND time >= '2023-05-01T00:00:00Z'
AND time < '2023-05-01T02:00:00Z'
GROUP BY
time(30m)
fill(previous)
time | 平均值 |
---|
2023-05-01T00:00:00Z | 29319.9092 |
2023-05-01T00:30:00Z | 29307.4416 |
2023-05-01T01:00:00Z | 29307.4416 |
2023-05-01T01:30:00Z | 29263.2886 |
结果集
如果至少有一行满足查询条件,InfluxDB Clustered 将在查询结果集中返回行数据。如果查询使用 GROUP BY
子句,则结果集包括以下内容
- 查询的
SELECT
子句中列出的列 - 一个
time
列,其中包含记录或组的时间戳 - 一个
iox::measurement
列,其中包含记录的 measurement(表)名称 - 查询的
GROUP BY
子句中列出的列;结果集中的每一行都包含用于分组的值
默认时间范围
如果查询未在 WHERE
子句 中指定时间范围,则 InfluxDB 使用 默认时间范围 进行过滤和按时间分组。如果查询包含 GROUP BY
子句,并且未在 WHERE
子句中指定时间范围,则默认时间组是 默认时间范围,并且结果集中的 time
列包含范围的开始时间 - 例如
SELECT mean(temp) FROM home GROUP BY room
time | 平均值 |
---|
1970-01-01T00:00:00Z | 22.623076923076926 |
time | 平均值 |
---|
1970-01-01T00:00:00Z | 22.16923076923077 |
GROUP BY 子句的显着行为
无法按字段分组
InfluxQL 不支持按字段对数据进行分组。
标签顺序无关紧要
GROUP BY
子句中列出的标签顺序不影响数据的分组方式。
按标签分组且无时间范围返回意外时间戳
time
列包含 默认时间范围 的开始时间。
按时间分组的数据可能返回意外时间戳
由于 GROUP BY time()
间隔使用预设的四舍五入的时间边界,这些边界独立于 WHERE
子句 中的时间条件,因此结果可能包含查询时间范围之外的时间戳。结果仅表示时间戳在指定时间范围内的数据,但输出时间戳由预设时间边界确定。
以下示例按 1 小时间隔分组数据,但 WHERE
子句中定义的时间范围仅涵盖窗口的一部分
SELECT MEAN(field)
FROM example
WHERE
time >= '2022-01-01T00:30:00Z'
AND time <= '2022-01-01T01:30:00Z'
GROUP BY time(1h)
注意:查询结果数据的第一行中的时间戳发生在查询时间范围的开始时间之前。查看原因。
示例数据
time | 字段 |
---|
2022-01-01T00:00:00Z | 8 |
2022-01-01T00:15:00Z | 4 |
2022-01-01T00:30:00Z | 0 |
2022-01-01T00:45:00Z | 8 |
2022-01-01T01:00:00Z | 5 |
2022-01-01T01:15:00Z | 0 |
2022-01-01T01:30:00Z | 8 |
2022-01-01T01:45:00Z | 8 |
2022-01-01T02:00:00Z | 9 |
2022-01-01T02:15:00Z | 6 |
2022-01-01T02:30:00Z | 3 |
2022-01-01T02:45:00Z | 0 |
查询结果
time | 字段 |
---|
2022-01-01T00:00:00Z | 4 |
2022-01-01T01:00:00Z | 5.25 |
2022-01-01T02:00:00Z | 6 |
为什么这些结果包含查询时间范围之外的时间戳?
GROUP BY time()
基于指定的时间间隔创建具有预定义时间边界的窗口。这些边界不是由查询时间范围决定的,但是,查询结果中的聚合值仅使用查询时间范围内的值计算。
time | 字段 |
---|
2022-01-01T00:00:00Z | 8 |
2022-01-01T00:15:00Z | 4 |
2022-01-01T00:30:00Z | 0 |
2022-01-01T00:45:00Z | 8 |
2022-01-01T01:00:00Z | 5 |
2022-01-01T01:15:00Z | 0 |
2022-01-01T01:30:00Z | 8 |
2022-01-01T01:45:00Z | 8 |
2022-01-01T02:00:00Z | 9 |
2022-01-01T02:15:00Z | 6 |
2022-01-01T02:30:00Z | 3 |
2022-01-01T02:45:00Z | 0 |
在查询的时间范围内无数据时填充
如果查询的时间范围内没有数据,则查询将忽略 fill()
。这是预期的行为。
如果不存在先前值,则用先前值填充
如果查询的时间范围内没有先前值,则 fill(previous)
不会填充空值。
如果不存在两个值进行插值,则使用线性插值填充
如果在查询的时间范围内,空值之前或之后没有值,则 fill(linear)
不会填充空值。
支持和反馈
感谢您成为我们社区的一份子!我们欢迎并鼓励您提供关于 InfluxDB Clustered 和此文档的反馈和错误报告。要获得支持,请使用以下资源
拥有年度合同或支持合同的客户可以联系 InfluxData 支持。