我有一个带有纪元值的表(每分钟一个,纪元本身以毫秒为单位)和温度。
select * from outdoor_temperature order by time desc;
time | value
---------------+-------
1423385340000 | 31.6
1423385280000 | 31.6
1423385220000 | 31.7
1423385160000 | 31.7
1423385100000 | 31.7
1423385040000 | 31.8
1423384980000 | 31.8
1423384920000 | 31.8
1423384860000 | 31.8
[...]
我想获得每天发生的最低值(和最高值,但可以是单独的查询),以及发生时的特定时间(最好是原始纪元时间)。我设法用date_trunc
设法做到了,但这给了我一般的一天,而不是那天的特定时间:
select
date_trunc('day',TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000) * INTERVAL '1 second') as timestamp,
min(value)
from outdoor_temperature
group by timestamp
order by min asc
limit 5;
timestamp | min
------------------------+------
2015-03-27 00:00:00+10 | 10.7
2015-03-28 00:00:00+10 | 10.8
2015-01-30 00:00:00+10 | 13.6
2015-03-17 00:00:00+10 | 14.0
2015-03-29 00:00:00+10 | 14.5
(5 rows)
我需要做某种加入魔法(我的加入是非常弱的),还是我从完全错误的方向攻击这个?我试过了DISTINCT ON
,但却没有成功。
答案 0 :(得分:2)
您可以从此查询开始:
SELECT date_trunc('minute',TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000) * INTERVAL '1 second') as timestamp, value AS temperature from _outdoor_temperature
显示两列,第一列是“epoch”,转换为具有“分钟”精度的时间戳。 由于您需要找到每天的最低/最高值,最好还是只有日期而不是时间戳的列:
SELECT
x.timestamp::date AS a,
x.timestamp AS b,
temperature AS c
FROM (
SELECT date_trunc('minute',TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000) * INTERVAL '1 second') as timestamp, value AS temperature from _outdoor_temperature
) AS x
现在您的日期为“a”列,时间戳为“b”列,温度值为最后一个“c”列。
最后一部分是使用“order by”结合“distinct on”表达式。这比group by更好,因为您正在查找一列的唯一值并查看另一列的关联:
select distinct on(y.a)
y.a,
y.b,
y.c
from (
SELECT
x.timestamp::date AS a,
x.timestamp AS b,
temperature AS c
FROM (
SELECT date_trunc('minute',TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000) * INTERVAL '1 second') as timestamp, value AS temperature from _outdoor_temperature
) AS x
) y
order by y.a, y.c
答案 1 :(得分:1)
select day::date, min_value_timestamp, min_value, max_value_timestamp, max_value
from
(
select distinct on (1)
date_trunc('day', timestamp with time zone 'epoch' + time/1000 * interval '1 second') as day,
timestamp with time zone 'epoch' + (time/1000 * interval '1 second') as min_value_timestamp,
value as min_value
from outdoor_temperature
order by 1, 3
) s
inner join
(
select distinct on (1)
date_trunc('day', timestamp with time zone 'epoch' + time/1000 * interval '1 second') as day,
timestamp with time zone 'epoch' + (time/1000 * interval '1 second') as max_value_timestamp,
value as max_value
from outdoor_temperature
order by 1, 3 desc
) v using (day)
order by 1
答案 2 :(得分:0)
好的,感谢@ voycheck的建议我最后添加了另一列类型为date
的列,并仅使用与time
字段对应的日期填充该列,因此该表看起来像这样:
Column | Type | Modifiers
--------+---------+-----------
time | bigint | not null
value | numeric |
date | date |
Indexes:
"outdoor_temperature_pkey" PRIMARY KEY, btree ("time")
"outdoor_temperature_date_idx" btree (date)
"outdoor_temperature_value_idx" btree (value)
然后大规模简化并加速了SQL查询:
SELECT time, value FROM (
SELECT DISTINCT ON (date)
date, time, value
FROM outdoor_temperature
ORDER BY date, value desc
) t
ORDER BY t.value desc;