数据库看起来像:
ID | volume | timestamp (timestamp without time zone)
1 | 300 | 2015-05-27 00:
1 | 250 | 2015-05-28 00:
2 | 13 | 2015-05-25 00:
1 | 500 | 2015-06-28 22:
1 | 100 | 2015-06-28 23:
2 | 11 | 2015-06-28 21:
2 | 15 | 2015-06-28 23:
有没有办法将每小时的价格历史合并到每天最早的1个月并将它们放回桌面?这意味着将每小时记录合并为1条记录,总金额和时间戳为00小时(我的意思是只有一天,2013-08-15 00:00:00)。
所以,想要结果:
ID | volume | timestamp
1 | 300 | 2015-05-27 00:
1 | 250 | 2015-05-28 00:
2 | 13 | 2015-05-25 00:
1 | 600 | 2015-06-28 00:
2 | 26 | 2015-06-28 00:
答案 0 :(得分:4)
根据没有时间的日期看起来像一个简单的组:
select id,
sum(volume) as volume,
timestamp::date as timestamp
from the_table
group by id, timestamp::date
order by id, timestamp::date;
timestamp::date
会将名为timestamp
的列(btw是列的可怕的名称)强制转换为date
,从而删除时间部分时间戳(数据类型)。
timestamp::date
具体是Postgres。 ANSI SQL等价物是cast(timestamp as date)
(我是否提到 timestamp 是列的可怕名称?)
答案 1 :(得分:1)
由于你想用这个新数据修改表,我想到了一个select into。以下是我的进展(见sql fiddle here):
以下是代码:
/*Step 1 : Select the data you need and insert it in a temporary table*/
SELECT
ID,
SUM(volume) as volume,
timestamp_field::date
INTO foo_temp
FROM foo
GROUP BY
ID,
timestamp_field::date
ORDER BY
ID,
timestamp_field::date;
/*Step 2 : Delete data from the table*/
DELETE FROM foo;
/*Step3 : Take data from the temporary table and insert it into the "main" table*/
INSERT INTO foo(ID,volume,timestamp_field)
SELECT * FROM foo_temp;
/*Step 4: Drop the temporary table*/
DROP TABLE foo_temp;
/*Step 5 : Yeah it works !*/
SELECT * FROM foo;
我必须承认@a_horse_with_no_name做了大部分工作,他的回答很优雅。
注意:可能有更好的方法来完成这项工作。
答案 2 :(得分:0)
感谢您的帮助@Pholochtairze和@a_horse_with_no_name 最终查询:
WITH merged_history AS (
SELECT item_id, SUM(history_volume) AS history_volume,
(SUM(history_medianprice * history_volume) / SUM(history_volume)) AS history_medianprice,
history_timestamp::date
FROM prices_history
WHERE history_timestamp < NOW()::date - INTERVAL '1 month'
GROUP BY item_id, history_timestamp::date),
upsert AS (
UPDATE prices_history AS h
SET history_volume = mh.history_volume, history_medianprice = mh.history_medianprice
FROM merged_history AS mh
WHERE h.item_id = mh.item_id AND h.history_timestamp = mh.history_timestamp RETURNING h.*)
INSERT INTO prices_history
SELECT item_id, history_volume, history_medianprice, history_timestamp
FROM merged_history
WHERE NOT EXISTS (
SELECT 1 FROM upsert AS u, merged_history AS mh
WHERE u.item_id = mh.item_id AND u.history_timestamp = mh.history_timestamp);
DELETE FROM prices_history
WHERE history_timestamp != history_timestamp::date
AND history_timestamp < NOW()::date - INTERVAL '1 month';
(完成此挑战需要2分钟(3米行):D我将每周运行一次。稍后会稍微修改一下,因为不需要合并已合并的数据)