postgresql 根据行顺序为记录生成分组列

pftdvrlh  于 2023-06-22  发布在  PostgreSQL
关注(0)|答案(3)|浏览(114)

我有从电子表格导入的Postgres数据,其中节标题已与数据沿着导入。是否有办法将节标题移动到它们自己的列中?我已经看过窗口函数,并尝试了自连接。
我确信类别名称将始终具有空的“责任”。它必须依赖于它们被插入的顺序,没有排序列。这合理吗?
我需要转换一下:
| 需要|责任|
| - -----|- -----|
| 场地维护||
| 树木/灌木养护|公园和娱乐|
| 移除树木|公共工程|
| 割草|公园和娱乐|
| 消防站割草|开火|
| 灌溉系统|公园和娱乐|
| 挡土墙/斜坡维修|资本项目|
| 楼宇维修||
| 清洁/再供应|建筑物使用者|
| 电气|设施维护|
| 地毯保养|设施运营|
| 发电机|设施维护|
| 设备|设施维护|
进入:
| 类别|需要|责任|
| - -----|- -----|- -----|
| 场地维护|树木/灌木养护|公园和娱乐|
| 场地维护|移除树木|公共工程|
| 场地维护|割草|公园和娱乐|
| 场地维护|消防站割草|开火|
| 场地维护|灌溉系统|公园和娱乐|
| 场地维护|挡土墙/斜坡维修|资本项目|
| 楼宇维修|清洁/再供应|建筑物使用者|
| 楼宇维修|电气|设施维护|
| 楼宇维修|地毯保养|设施运营|
| 楼宇维修|发电机|设施维护|
| 楼宇维修|设备|设施维护|

os8fio9y

os8fio9y1#

正如@eshirvana已经指出的那样,没有可靠的方法来完成这项任务。虽然如果您仍然不可能有一个增量值来唯一地标识行的顺序,但您可以利用“ctid”系统值,该值保存记录在该表中的插入顺序(如果您批量插入,使用这种方法仍然不可靠)。
这就是你如何解决这个问题:

  • 使用responsibility = NULL上的运行求和重新生成分区,按“ctid”排序
  • 在责任为空的情况下,将类别字段生成为最大“* 需要 *”值
  • 删除头记录,通过选择“* 责任 *”不为空的所有记录
WITH cte AS (
    SELECT tab.*,
           SUM(responsibility IS NULL::INT) OVER(ORDER BY ctid) AS parts
    FROM tab
), cte2 AS (
    SELECT MAX(need) FILTER(WHERE responsibility IS NULL) OVER(PARTITION BY parts) AS category,
           cte.*
    FROM cte
)
SELECT * FROM cte2 WHERE responsibility IS NOT NULL

查看演示here

j2datikz

j2datikz2#

把它放在这里,因为它不适合在评论部分:
如前所述here
如果未选择排序,则将以未指定的顺序返回行。在这种情况下,实际顺序将取决于扫描和连接计划类型以及磁盘上的顺序,但不能依赖于此。
要为插入日期添加一个新列,您必须alter the table并添加该列并使用适当的值填充它,无论是插入还是手动更新它们:

alter table [table_name] add column InsertDate timestamp

有关详细信息,请参阅上述文档。
请记住,这只是一种方法,不一定是最好的方法。

kxkpmulp

kxkpmulp3#

这似乎是last non-null难题的一个例子。策略是派生一个row_number()列,将您想要“填充”的值分组,以便为您的category创建派生的最后非空列

SELECT *
FROM (
    WITH cte AS (
            SELECT *
                ,MAX(CASE 
                        WHEN category IS NOT NULL
                            THEN rn
                        END) OVER (
                    ORDER BY rn ROWS UNBOUNDED PRECEDING
                    ) AS grp
            FROM (
                SELECT row_number() OVER (
                        ORDER BY NULL
                        ) AS rn
                    ,responsibility
                    ,CASE 
                        WHEN responsibility IS NULL
                            THEN NULL
                        ELSE need
                        END AS _need
                    ,CASE 
                        WHEN responsibility IS NULL
                            THEN need
                        END AS category
                FROM test
                ) AS t2
            )
    SELECT MAX(category) OVER (
            PARTITION BY grp ORDER BY rn ROWS UNBOUNDED PRECEDING
            ) AS _category
        ,_need
        ,responsibility
    FROM cte
    ) AS t3
WHERE responsibility IS NOT NULL;

demo在这里

相关问题