[英]Postgres: Transform Continous Rows Into a Discrete Rows
I'm not sure wether the title is correct.我不确定标题是否正确。 I've spent some time to find the best title suited for this case.
我花了一些时间来找到最适合这种情况的标题。
Let say.说吧。 I have data in this format:
我有这种格式的数据:
| id | room | changes | created_at |
|----|------|------------------|-----------------|
| 1 | A | [free, occupied] | 2021-11-1 18:00 |
| 2 | B | [free, occupied] | 2021-11-1 20:30 |
| 3 | B | [occupied, free] | 2021-11-1 23:30 |
| 4 | A | [occupied, free] | 2021-11-2 00:15 |
| 5 | B | [free, occupied] | 2021-11-2 01:00 |
The output required will be所需的 output 将是
+----+------+----------+-----------------+
| id | room | occupied | Period |
+----+------+----------+-----------------+
| 1 | A | NO | 2021-11-1 18:00 |
| 2 | B | NO | 2021-11-1 18:00 |
| 3 | A | NO | 2021-11-1 19:00 |
| 4 | B | NO | 2021-11-1 19:00 |
| 5 | A | YES | 2021-11-1 20:00 |
| 6 | B | NO | 2021-11-1 20:00 |
| 7 | A | YES | 2021-11-1 21:00 |
| 8 | B | NO | 2021-11-1 21:00 |
| 9 | A | YES | 2021-11-1 22:00 |
| 10 | B | NO | 2021-11-1 22:00 |
| 11 | A | YES | 2021-11-1 23:00 |
| 12 | B | YES | 2021-11-1 23:00 |
| 13 | A | YES | 2021-11-2 00:00 |
| 14 | B | YES | 2021-11-2 00:00 |
| 15 | A | NO | 2021-11-2 01:00 |
| 16 | B | YES | 2021-11-2 01:00 |
| 17 | A | NO | 2021-11-2 02:00 |
| 18 | B | YES | 2021-11-2 02:00 |
+----+------+----------+-----------------+
The output generated using this logic:使用此逻辑生成的 output:
First some comments about your question:首先对您的问题发表一些评论:
Then I propose you a query which implements the following rules:然后我建议您执行以下规则的查询:
This query may provide a result slightly different from your expectation, but it can be easily adjusted.此查询提供的结果可能与您的预期略有不同,但可以轻松调整。
SELECT t.id -- may be NULL according to the LEFT JOIN and this is a gap with the expected result as presented in the question
, r.room
, CASE
WHEN t.room = r.room AND t.changes = '[free, occupied]'
THEN 'YES'
WHEN t.room = r.room AND t.changes = '[occupied, free]'
THEN 'NO'
WHEN ( jsonb_agg(t.changes)
FILTER (WHERE t.room = r.room)
OVER (PARTITION BY r.room ORDER BY p.created_at ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
)->>-1 IS NOT DISTINCT FROM '[free, occupied]'
THEN 'YES'
ELSE 'NO'
END AS occupied
, p.created_at AS period
FROM
( SELECT DISTINCT ON (created_at) created_at
FROM your_table
) AS p
CROSS JOIN
( SELECT DISTINCT ON (room) room
FROM your_table
) AS r
LEFT JOIN your_table AS t
ON t.room = r.room
AND t.created_at = p.created_at
ORDER BY p.created_at, r.room
In the result, the id column corresponds to the id value in your_table .结果, id列对应于your_table中的id值。 So this id is NULL when the output row doesn't correspond to any rows in your_table .
因此,当 output 行与 your_table 中的任何行都不对应时,此id为NULL 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.