2012-05-16 3 views
0

Я написал веб-приложение для развертывания в heroku. Я написал его с помощью PostgreSQL 9.1.2. Но, похоже, что бесплатный общий db на heroku - это только postgres 8.3. Они обновляются до 9. Что-то скоро, но до тех пор один из моих SQL-запросов не работает. Это:Как вы можете выполнять функции окна в PostgreSQL 8.3

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 

Возможно ли переписать это для работы в PostgreSQL 8.3?

+0

Вам нужно будет подождать обновления 9.x –

ответ

2

Обратите внимание, что Window functions doesn't exists в PostgreSQL before 8.4.


EDIT2:

Вы сделали меня очень любопытными, и я играл с запросами.

Некоторые вещи, чтобы отметить первый:

  1. Для того, чтобы достичь желаемого результата, вам придется присоединиться к столу себе много раз. Учитывая, что PostgreSQL 8.3 не поддерживает CTE, я создал представление. К счастью, в вашем случае требуется только одно представление, поскольку вы используете те же условия OVER() для всех оконных функций;

  2. row_number должен использоваться для работы с подмножествами данных, поэтому я добавил это поле в представление;

  3. Чтобы сформировать PARTITION, вы должны использовать оператор = на объединенных таблицах для всех полей в предложении PARTITION;

  4. row_number сформирован с использованием подзапроса (без соединения) и подсчета всех строк, соответствующих разделу, и полей ORDER BY, меньших или равных текущему. Обратите внимание, что если поле ORDER BY не уникально, этот подход не будет работать! Если это не так, то создайте такое поле.

  5. Для имитации ORDER BY положения о не являющихся row_number функций, вы присоединитесь на row_number полях, делая это время +1, -1, min() или max() на присоединяемой стороне, соответствие lead(), lag(), first_value() и last_value() функции соответственно.

Пожалуйста, рассмотрим точку выше!

Ваш запрос может путем изменен следующим образом (сравните вывод перед использованием):

-- 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 
    -- ... 

Я использовал модифицированную выборочные данные из Window functions and more "local" aggregation и создали песочницу, чтобы показать, как это работает на SQL Fiddle.

Тем не менее, учитывая, что все разработки были выполнены 9.1.2, я подумал бы дважды, прежде чем идти этим путем.

+0

Невозможно это сделать с помощью соединений? – dan

+0

@ dan, я предоставил совместное решение, надеюсь, что он может вас устраивать. – vyegorov

+0

wow спасибо за это – dan

Смежные вопросы