聚合 SQL 中缺少布尔值的行
Aggregating rows in SQL with missing Booleans
我有下面的 SQL 脚本,其中 returns 来自 PostgreSQL 数据库视图 table 的以下数据。
SELECT
"V_data".macaddr,
"V_data".sensorid,
"V_data".ts,
"V_data".velocity,
"V_data".temp,
"V_data".highspeed,
"V_data".hightemp,
"V_data".distance,
FROM
sensordb."V_data"
WHERE
"V_data".macaddr like '%abcdef'
AND
(
("V_data".sensorid = 'abc1') or ("V_data".sensorid = 'a2bc') or ("V_data".sensorid = 'ab3c')
)
AND
"V_data".ts >= 1616370867000
ORDER BY
"V_data".ts DESC;
输出
macaddr
sensorid
ts
velocity
temp
highspeed
hightemp
distance
abcdef
abc1
1616370867010
25
32
52
abcdef
a2bc
1616370867008
27
35
T
51
abcdef
ab3c
1616370867006
26
30
50
abcdef
abc1
1616370867005
24
36
T
50
abcdef
a2bc
1616370867004
27
31
50
abcdef
abc1
1616370867002
21
30
T
48
abcdef
ab3c
1616370867000
22
33
F
46
我想聚合行,以便我获得每个传感器的 ts、速度、温度、距离的最新读数。
对于高速和高温布尔值,我想要最新可用的布尔值,如果没有可用的布尔值,我想要一个空单元格。
预期输出
macaddr
sensorid
ts
velocity
temp
highspeed
hightemp
distance
abcdef
abc1
1616370867010
25
32
T
T
52
abcdef
a2bc
1616370867008
27
35
T
51
abcdef
ab3c
1616370867006
26
30
F
50
我怎样才能简化这个任务?
谢谢。
嗯。 . .对于除布尔列之外的所有列 DISTINCT ON
都可以。但是那些布尔值很棘手。您可以对布尔值使用一些技巧。
相反,让我们去 ROW_NUMBER()
获取最近的行。并且 fiddle 使用数组获取最新的布尔值:
SELECT d.macaddr, d.sensorid,
MAX(d.ts) as ts,
MAX(d.velocity) FILTER (WHERE seqnum = 1) as velocity,
MAX(d.temp) FILTER (WHERE seqnum = 1) as temp,
(ARRAY_REMOVE(ARRAY_AGG(d.highspeed ORDER BY ts DESC), NULL))[1] as highspeed,
(ARRAY_REMOVE(ARRAY_AGG(d.hightemp ORDER BY ts DESC), NULL))[1] as hightemp
MAX(d.distance) FILTER (WHERE seqnum = 1)
FROM (SELECT d.*,
ROW_NUMBER() OVER (PARTITION BY d.macaddr, d.sensorid ORDER BY ts DESC) as seqnum
FROM sensordb."V_data" d
WHERE d.macaddr like '%abcdef' AND
d.sensorid IN ('abc1', 'a2bc', 'ab3c') AND
d.ts >= 1616370867000
) d
GROUP BY d.macaddr, d.sensorid
ORDER BY d.ts DESC;
您可以使用 DISTINCT ON
(仅在 PostgreSQL afaik 中可用)来简化此查询。你可以这样做:
with
q as (
-- your query here
)
select
l.macaddr, l.sensorid, l.ts, l.velocity, l.temp,
s.highspeed, t.hightemp,
l.distance
from (
select distinct on (sensorid) *
from q
order by sensorid, ts desc
) l
left join (
select distinct on (sensorid) *
from q
where highspeed is not null
order by sensorid, ts desc
) s on s.sensorid = l.sensorid
left join (
select distinct on (sensorid) *
from q
where hightemp is not null
order by sensorid, ts desc
) t on t.sensorid = l.sensorid
我有下面的 SQL 脚本,其中 returns 来自 PostgreSQL 数据库视图 table 的以下数据。
SELECT
"V_data".macaddr,
"V_data".sensorid,
"V_data".ts,
"V_data".velocity,
"V_data".temp,
"V_data".highspeed,
"V_data".hightemp,
"V_data".distance,
FROM
sensordb."V_data"
WHERE
"V_data".macaddr like '%abcdef'
AND
(
("V_data".sensorid = 'abc1') or ("V_data".sensorid = 'a2bc') or ("V_data".sensorid = 'ab3c')
)
AND
"V_data".ts >= 1616370867000
ORDER BY
"V_data".ts DESC;
输出
macaddr | sensorid | ts | velocity | temp | highspeed | hightemp | distance |
---|---|---|---|---|---|---|---|
abcdef | abc1 | 1616370867010 | 25 | 32 | 52 | ||
abcdef | a2bc | 1616370867008 | 27 | 35 | T | 51 | |
abcdef | ab3c | 1616370867006 | 26 | 30 | 50 | ||
abcdef | abc1 | 1616370867005 | 24 | 36 | T | 50 | |
abcdef | a2bc | 1616370867004 | 27 | 31 | 50 | ||
abcdef | abc1 | 1616370867002 | 21 | 30 | T | 48 | |
abcdef | ab3c | 1616370867000 | 22 | 33 | F | 46 |
我想聚合行,以便我获得每个传感器的 ts、速度、温度、距离的最新读数。 对于高速和高温布尔值,我想要最新可用的布尔值,如果没有可用的布尔值,我想要一个空单元格。
预期输出
macaddr | sensorid | ts | velocity | temp | highspeed | hightemp | distance |
---|---|---|---|---|---|---|---|
abcdef | abc1 | 1616370867010 | 25 | 32 | T | T | 52 |
abcdef | a2bc | 1616370867008 | 27 | 35 | T | 51 | |
abcdef | ab3c | 1616370867006 | 26 | 30 | F | 50 |
我怎样才能简化这个任务?
谢谢。
嗯。 . .对于除布尔列之外的所有列 DISTINCT ON
都可以。但是那些布尔值很棘手。您可以对布尔值使用一些技巧。
相反,让我们去 ROW_NUMBER()
获取最近的行。并且 fiddle 使用数组获取最新的布尔值:
SELECT d.macaddr, d.sensorid,
MAX(d.ts) as ts,
MAX(d.velocity) FILTER (WHERE seqnum = 1) as velocity,
MAX(d.temp) FILTER (WHERE seqnum = 1) as temp,
(ARRAY_REMOVE(ARRAY_AGG(d.highspeed ORDER BY ts DESC), NULL))[1] as highspeed,
(ARRAY_REMOVE(ARRAY_AGG(d.hightemp ORDER BY ts DESC), NULL))[1] as hightemp
MAX(d.distance) FILTER (WHERE seqnum = 1)
FROM (SELECT d.*,
ROW_NUMBER() OVER (PARTITION BY d.macaddr, d.sensorid ORDER BY ts DESC) as seqnum
FROM sensordb."V_data" d
WHERE d.macaddr like '%abcdef' AND
d.sensorid IN ('abc1', 'a2bc', 'ab3c') AND
d.ts >= 1616370867000
) d
GROUP BY d.macaddr, d.sensorid
ORDER BY d.ts DESC;
您可以使用 DISTINCT ON
(仅在 PostgreSQL afaik 中可用)来简化此查询。你可以这样做:
with
q as (
-- your query here
)
select
l.macaddr, l.sensorid, l.ts, l.velocity, l.temp,
s.highspeed, t.hightemp,
l.distance
from (
select distinct on (sensorid) *
from q
order by sensorid, ts desc
) l
left join (
select distinct on (sensorid) *
from q
where highspeed is not null
order by sensorid, ts desc
) s on s.sensorid = l.sensorid
left join (
select distinct on (sensorid) *
from q
where hightemp is not null
order by sensorid, ts desc
) t on t.sensorid = l.sensorid