patternsqlModerate
PostgreSQL query with max and min date plus associated id per row
Viewed 0 times
postgresqlperwithquerydateminplusmaxassociatedand
Problem
I have the following table:
I want to have the following view
with columns that specify the ids of the max and min trans_time.
How do I do that?
CREATE TABLE trans (
id SERIAL PRIMARY KEY,
trans_date date,
trans_time time
);I want to have the following view
CREATE OR REPLACE VIEW daily_trans AS
SELECT trans_date,
max(trans_time) as first,
min(trans_time) as last,
calculate_status(min(trans_time), max(trans_time)) as status
GROUP BY trans_datewith columns that specify the ids of the max and min trans_time.
How do I do that?
Solution
You can calculate this in one step with window functions:
I added
If you are not familiar with window functions, be sure to read this chapter of the manual.
How you to combine
CREATE OR REPLACE VIEW daily_trans AS
SELECT DISTINCT
trans_date
, first_value(trans_time) OVER w AS first_time
, first_value(id) OVER w AS first_id
, last_value(trans_time) OVER w AS last_time
, last_value(id) OVER w AS last_id
, calculate_status(min(trans_time) OVER w
, max(trans_time) OVER w) AS status
FROM trans
WINDOW w AS (PARTITION BY trans_date ORDER BY trans_time, id
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
ORDER BY 1;I added
id as secondary ORDER column in the window clause, to make the sort order stable in case of identical times per day.If you are not familiar with window functions, be sure to read this chapter of the manual.
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING is a not so commonly used clause to adjust the window frame, because we want last_value() to always return the last value of the whole partition (the date), not the last value up to the current (including peers) according to the sort order.How you to combine
DISTINCT with window functions:- PostgreSQL: running count of rows for a query 'by minute'
Code Snippets
CREATE OR REPLACE VIEW daily_trans AS
SELECT DISTINCT
trans_date
, first_value(trans_time) OVER w AS first_time
, first_value(id) OVER w AS first_id
, last_value(trans_time) OVER w AS last_time
, last_value(id) OVER w AS last_id
, calculate_status(min(trans_time) OVER w
, max(trans_time) OVER w) AS status
FROM trans
WINDOW w AS (PARTITION BY trans_date ORDER BY trans_time, id
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
ORDER BY 1;Context
StackExchange Database Administrators Q#9798, answer score: 13
Revisions (0)
No revisions yet.