使用 Grafana 的(TimescaleDB)SQL 插件进行多连接的 Groupby 问题
Posted
技术标签:
【中文标题】使用 Grafana 的(TimescaleDB)SQL 插件进行多连接的 Groupby 问题【英文标题】:Groupby issue on multiple join using Grafana's (TimescaleDB) SQL plugin 【发布时间】:2021-04-29 12:06:57 【问题描述】:我正在使用 Grafana 的 SQL 插件来查询 TimescaleDB 数据库。
数据库将天气信息存储为
| timestamp | location_id | data_type_id | value |
其中location_id
和data_type_id
是表locations
的外键描述位置,weather_data_types
定义测量类型(温度、相对湿度...)。
我想查询某个时间范围内的数据,按位置和类型分组。
我设法按其中一个分组,但不能同时分组。
这适用于按位置分组:
SELECT
$__timeGroupAlias("timestamp", $__interval),
avg(value),
locations.name
FROM weather_data
JOIN locations ON weather_data.location_id = locations.id
GROUP BY 1, locations.name
ORDER BY 1
这适用于按类型分组:
SELECT
$__timeGroupAlias("timestamp", $__interval),
avg(value),
weather_data_types.name
FROM weather_data
JOIN weather_data_types ON weather_data.type_id = weather_data_types.id
GROUP BY 1, weather_data_types.name
ORDER BY 1
这不起作用:
SELECT
$__timeGroupAlias("timestamp", $__interval),
avg(value),
locations.name,
weather_data_types.name
FROM weather_data
JOIN locations ON weather_data.location_id = locations.id
JOIN weather_data_types ON weather_data.type_id = weather_data_types.id
GROUP BY 1, locations.name, weather_data_types.name
ORDER BY 1
更具体地说,我收到以下错误
Value column must have numeric datatype, column: name type: string value: relative_humidity
似乎第三个 groupby (静默)没有发生,并且返回了 weather_data_types.name
,Grafana 抱怨说它无法绘制字符串。
将其更改为返回(整数)id 会删除错误消息
SELECT
$__timeGroupAlias("timestamp", $__interval),
avg(value),
locations.name,
weather_data_types.id
FROM weather_data
JOIN locations ON weather_data.location_id = locations.id
JOIN weather_data_types ON weather_data.type_id = weather_data_types.id
GROUP BY 1, locations.name, weather_data_types.id
ORDER BY 1
但绘制了两个系列:avg
和 id
,这表明未应用 groupby 类型。
我的查询有什么问题吗?是 Grafana 插件的问题吗?
我认为这并不重要,但这里是模型,用 SQLAlchemy 定义,希望不言自明。
class Location(Base):
__tablename__ = "locations"
id = sqla.Column(sqla.Integer, primary_key=True)
name = sqla.Column(sqla.String(80), unique=True, nullable=False)
country = sqla.Column(sqla.String(80), nullable=False)
latitude = sqla.Column(sqla.Float(), nullable=False)
longitude = sqla.Column(sqla.Float(), nullable=False)
class WeatherDataTypes(Base):
__tablename__ = "weather_data_types"
id = sqla.Column(sqla.Integer, primary_key=True)
name = sqla.Column(sqla.String(80), unique=True, nullable=False)
description = sqla.Column(sqla.String(500), nullable=False)
unit = sqla.Column(sqla.String(20), nullable=False)
min_value = sqla.Column(sqla.Float)
max_value = sqla.Column(sqla.Float)
class WeatherData(Base):
__tablename__ = "weather_data"
timestamp = sqla.Column(sqla.DateTime(timezone=True), primary_key=True)
location_id = sqla.Column(
sqla.Integer,
sqla.ForeignKey('locations.id'),
nullable=False,
primary_key=True
)
location = sqla.orm.relationship('Location')
type_id = sqla.Column(
sqla.Integer,
sqla.ForeignKey('weather_data_types.id'),
nullable=False,
primary_key=True
)
type = sqla.orm.relationship('WeatherDataTypes')
value = sqla.Column(sqla.Float)
【问题讨论】:
【参考方案1】:直接向 postgresql 发送请求帮助我了解发生了什么。
显然,当查询返回一列值和一列字符串时,Grafana 插件假定要绘制这些值,并且字符串列旨在用作绘图的标签。
我认为插件使用 groupby 来排序提取列以使其成为标签信息,但这种魔法不适用于两个字符串列,因为插件不会连接值本身。因此,插件抱怨第二个字符串列不是数字,这是一种误导,因为它不会抱怨第一个字符串列。
我可以通过将我用于 groupby 的值连接到单个列中来使其工作:
SELECT
time_bucket('21600s',"timestamp") AS "time",
avg(value),
CONCAT(locations.name, ' ', weather_data_types.name) AS "name"
FROM weather_data
JOIN locations ON weather_data.location_id = locations.id
JOIN weather_data_types ON weather_data.type_id = weather_data_types.id
GROUP BY 1, locations.name, weather_data_types.name
ORDER BY 1
返回
time | avg | name
------------------------+--------------------+---------------------------
插件正确解释。
【讨论】:
以上是关于使用 Grafana 的(TimescaleDB)SQL 插件进行多连接的 Groupby 问题的主要内容,如果未能解决你的问题,请参考以下文章
时序数据库新手,从TimescaleDB for Grafana中选择数据速度慢,查询复杂
快速入门:Java 连接使用 时序数据库 TimescaleDB