Reputation: 1605
I have written a web app to be deployed to heroku. I wrote it using PostgreSQL 9.1.2. But it seems that the free shared db on heroku is only postgres 8.3. They are upgrading to 9. Something sometime soon, but until then, one of my SQL queries doesn't work. It is:
SELECT id, route_id, location_id, order_id, blogtext,
lead(id) over (PARTITION BY route_id ORDER BY order_id ASC) AS next_id,
lead(location_id) over (PARTITION BY route_id ORDER BY order_id ASC) AS next_location_id,
lag(id) over (PARTITION BY route_id ORDER BY order_id ASC) as previous_id,
lag(location_id) over (PARTITION BY route_id ORDER BY order_id ASC) AS previous_location_id,
row_number() over (PARTITION BY route_id ORDER BY order_id ASC) AS indx
Is it possible to re-write this to work on PostgreSQL 8.3?
Upvotes: 0
Views: 2169
Reputation: 22845
Please, note, that Window functions doesn't exists in PostgreSQL before 8.4.
EDIT2:
You made me really curios and I've played around with the queries.
Some things to note first:
In order to achieve the desired result, you'll have to join table with itself many times. Given PostgreSQL 8.3 is not supporting CTE, I've created a view. Luckily in your case only one view is required, as you use the same OVER ()
conditions for all window functions;
row_number
should be used to operate on data subsets, so I've added this field to the view;
To form PARTITION
, you should use =
operator on joined tables for all fields in the PARTITION
clause;
row_number
is formed using subquery (no join) and counting all rows that match partition and have ORDER BY
fields less or equal to the current one. Note, that if ORDER BY
field is not unique, this approach will not work!
If it is not the case, then create such field.
To simulate ORDER BY
clause on non row_number
functions, you join on row_number
fields, making it being +1
, -1
, min()
or max()
on the joined side, matching lead()
, lag()
, first_value()
and last_value()
functions respectively.
Please, consider point 4 above!
Your query can by changed the following way (compare output before using):
-- First, create a support view
CREATE VIEW table_v AS
SELECT id, route_id, location_id, order_id, blogtext,
(SELECT count(*) FROM table
WHERE route_id = t.route_id AND order_id <= t.order_id) AS row_number
FROM table t;
-- Now, the query
SELECT t.id, t.route_id, t.location_id, t.order_id, t.blogtext,
tlead.id AS next_id, tlead.location_id AS next_location_id,
tlag.id AS previous_id, tlag.location_id AS previous_location_id,
t.row_number AS indx
FROM table_v t
LEFT JOIN table_v tlead
ON tlead.route_id = t.route_id AND tlead.row_number = t.row_number + 1
LEFT JOIN table_v tlag
ON tlag.route_id = t.route_id AND tlag.row_number = t.row_number - 1
--
-- proceed with the query here
-- ...
I've used modified sample data from Window functions and more "local" aggregation and created a sandbox to show how it works on the SQL Fiddle.
Still, given all development was done on 9.1.2 I would think twice before going this way.
Upvotes: 2