问题
I need your help to modify a query to accomplish the requirement.
According to the GATHER_TIME, I want to show the VALUE of the NAMEs. The query runs every 1 minute, and it should get 2 rows all the time. In case, there is no data at that time, it should get the past( 1 minute earlier ) data for the Name.
Here, specific requirement is that I should not consider seconds value in Timestamp value(GATHER_TIME).
I tried to make a query like below. It only gets the latest data.
Can you help me out?
Query
select NAME,sum(VALUE)
FROM TestTable
WHERE substring(to_char(gather_time,'YYYY-MM-DD HH24:MI:SS'),1,16) IN ( SELECT MAX(substring(to_char(gather_time,'YYYY-MM-DD HH24:MI:SS'),1,16)) FROM TestTable )
GROUP BY NAME
Table Data
NAME COL1 COL2 GATHER_TIME VALUE
------------------------------------------------
first prince PQ1 2015-12-29 13:10:33 11
first prince PQ2 2015-12-29 13:10:33 14
first prince PQ3 2015-12-29 13:10:33 18
first prince PQ4 2015-12-29 13:10:33 19
second prince TT1 2015-12-29 13:10:59 20
second prince TT2 2015-12-29 13:10:59 29
second prince TT3 2015-12-29 13:10:59 43
first prince PQ1 2015-12-29 13:11:37 71
first prince PQ2 2015-12-29 13:11:37 74
first prince PQ3 2015-12-29 13:11:37 78
first prince PQ4 2015-12-29 13:11:37 79
Required result
@ Query time: 2015-12-29 13:10:59
first 62
second 92
@ Query time: 2015-12-29 13:11:59
first 302
second 92
Added:
Sorry. I should have put more detail test data. Updated it.
If two columns are used in GROUP BY:: ( Need to be verified )
SELECT DISTINCT ON (name,col1,gather_time) name,col1,SUM(value)
FROM test_table
GROUP BY name,col1,gather_time
ORDER BY gather_time DESC
LIMIT 2;
回答1:
-- DDL
CREATE TABLE test_table(
name TEXT,
col2 TEXT,
gather_time TIMESTAMP,
value INTEGER
);
--sample data
INSERT INTO test_table VALUES
('first','PQ1','2015-12-29 13:10:33'::TIMESTAMP, 11),
('first','PQ2','2015-12-29 13:10:33'::TIMESTAMP, 14),
('first','PQ3','2015-12-29 13:10:33'::TIMESTAMP, 18),
('first','PQ4','2015-12-29 13:10:33'::TIMESTAMP, 19),
('second','TT1','2015-12-29 13:10:59'::TIMESTAMP, 20),
('second','TT2','2015-12-29 13:10:59'::TIMESTAMP, 29),
('second','TT3','2015-12-29 13:10:59'::TIMESTAMP, 43),
('first','PQ1','2015-12-29 13:11:37'::TIMESTAMP, 71),
('first','PQ2','2015-12-29 13:11:37'::TIMESTAMP, 74),
('first','PQ3','2015-12-29 13:11:37'::TIMESTAMP, 78),
('first','PQ4','2015-12-29 13:11:37'::TIMESTAMP, 79);
--query to run every minute
SELECT name,SUM(value) FROM test_table
WHERE gather_time <= now()
GROUP BY name,gather_time
ORDER BY gather_time DESC
LIMIT 2;
OR using function:
CREATE OR REPLACE FUNCTION get_2latest_agg_rows(qtime timestamp)
RETURNS TABLE (
order_name TEXT,
sum_value BIGINT
) AS $$
BEGIN
RETURN QUERY
SELECT name as order_name,SUM(value) as agg_result FROM test_table
WHERE gather_time <= qtime::TIMESTAMP
GROUP BY name,gather_time
ORDER BY gather_time DESC
LIMIT 2;
END;
$$ LANGUAGE plpgsql;
--sample run
SELECT * FROM get_2latest_agg_rows('2015-12-29 13:11:59'::TIMESTAMP);
回答2:
What if you will sort by gather_time and use limit 2 to get the latest 2 rows? Will that fit the requirments?
select NAME,sum(VALUE)
FROM TestTable
ORDER BY gather_time DESC
LIMIT 2;
来源:https://stackoverflow.com/questions/34575271/how-to-get-the-latest-2-rows-postgresql