Это трудно сделать в чистом SQL.Я бы прибегнул к процедуре plpgsql .
Скажем, ваша таблица выглядит следующим образом:
(В следующий раз будьте так любезны, что опубликуете определение таблицы. Стоит больше тысячислова.)
create table p (
id serial primary key -- or whatever your primary key is!
, company_id int4 NOT NULL
, create_time timestamp NOT NULL
, for_sale bool NOT NULL
);
Используйте функцию plpgsql следующим образом:
CREATE OR REPLACE FUNCTION f_p_group()
RETURNS void AS
$BODY$
DECLARE
g_id integer := 1;
last_time timestamp;
last_company_id integer;
r p%ROWTYPE;
BEGIN
-- If the table is huge, special settings for these parameters will help
SET temp_buffers = '100MB'; -- more RAM for temp table, adjust to actual size of p
SET work_mem = '100MB'; -- more RAM for sorting
-- create temp table just like original.
CREATE TEMP TABLE tmp_p ON COMMIT DROP AS
SELECT * FROM p LIMIT 0; -- no rows yet
-- add group_id.
ALTER TABLE tmp_p ADD column group_id integer;
-- loop through table, write row + group_id to temp table
FOR r IN
SELECT * -- get the whole row!
FROM p
-- WHERE for_sale -- commented out, after it vanished from the question
ORDER BY company_id, create_time -- group by company_id first, there could be several groups intertwined
LOOP
IF r.company_id <> last_company_id OR (r.create_time - last_time) > interval '10 min' THEN
g_id := g_id + 1;
END IF;
INSERT INTO tmp_p SELECT r.*, g_id;
last_time := r.create_time;
last_company_id := r.company_id;
END LOOP;
TRUNCATE p;
ALTER TABLE p ADD column group_id integer; -- add group_id now
INSERT INTO p
SELECT * FROM tmp_p; -- ORDER BY something?
ANALYZE p; -- table has been rewritten, no VACUUM is needed.
END;
$BODY$
LANGUAGE plpgsql;
Вызовите один раз, затем отбросьте:
SELECT f_p_group();
DROP FUNCTION f_p_group();
Теперь все участникигруппы согласно вашему определению доля group_id
.
Редактировать после редактирования вопроса
Я добавил еще пару вещей:
- Считать таблицу во временную таблицу (упорядочение в процессе), сделать всеобновите там, обрежьте исходную таблицу, добавьте group_id и запишите обновленные строки из временной таблицы за один раз.Должно быть намного быстрее и не нуждаться в вакууме впоследствии.Но вам нужно немного оперативной памяти для этого
for_sale
, игнорируемого в запросе, после того как его больше нет в вопросе. - Подробнее о % ROWTYPE .
- Прочтите здесь о work_mem и temp_buffers .
- TRUNCATE, ANALYZE, TEMP TABLE, ALTER TABLE, ... все в прекрасном руководстве
- Я проверил это с pg 9.0.должен работать в 8.4 - 9.0 и, возможно, более старых версиях.