У меня есть список дат и идентификаторов, и я хотел бы свернуть их в периоды фактических дат внутри каждого идентификатора.
Для таблицы со столбцами «testid» и «pulldate» втаблица с именем "data":
| A79 | 2010-06-02 |
| A79 | 2010-06-03 |
| A79 | 2010-06-04 |
| B72 | 2010-04-22 |
| B72 | 2010-06-03 |
| B72 | 2010-06-04 |
| C94 | 2010-04-09 |
| C94 | 2010-04-10 |
| C94 | 2010-04-11 |
| C94 | 2010-04-12 |
| C94 | 2010-04-13 |
| C94 | 2010-04-14 |
| C94 | 2010-06-02 |
| C94 | 2010-06-03 |
| C94 | 2010-06-04 |
Я хочу создать таблицу со столбцами "testid", "group", "start_date", "end_date":
| A79 | 1 | 2010-06-02 | 2010-06-04 |
| B72 | 2 | 2010-04-22 | 2010-04-22 |
| B72 | 3 | 2010-06-03 | 2010-06-04 |
| C94 | 4 | 2010-04-09 | 2010-04-14 |
| C94 | 5 | 2010-06-02 | 2010-06-04 |
Вот код, который я придумал:
SELECT t2.testid,
t2.group,
MIN(t2.pulldate) AS start_date,
MAX(t2.pulldate) AS end_date
FROM(SELECT t1.pulldate,
t1.testid,
SUM(t1.check) OVER (ORDER BY t1.testid,t1.pulldate) AS group
FROM(SELECT data.pulldate,
data.testid,
CASE
WHEN data.testid=LAG(data.testid,1)
OVER (ORDER BY data.testid,data.pulldate)
AND data.pulldate=date (LAG(data.pulldate,1)
OVER (PARTITION BY data.testid
ORDER BY data.pulldate)) + integer '1'
THEN 0
ELSE 1
END AS check
FROM data
ORDER BY data.testid, data.pulldate) AS t1) AS t2
GROUP BY t2.testid,t2.group
ORDER BY t2.group;
Я использовал оконную функцию LAG для сравнения каждой строки с предыдущей, поставив 1, если мне нужно увеличить значение, чтобы начать новую группу, затем я делаютекущую сумму в этом столбце, а затем объединить в комбинации «группа» и «тестид».
Есть ли лучший способ для достижения моей цели, или эта операция имеет имя?
Я использую PostgreSQL 8.4