使用最后一个值填充递归SQL上的空白空间

时间:2016-09-12 14:00:43

标签: sql postgresql postgresql-9.5

这是我用来从我的表中获取包含父子值的数据的SQL查询:

WITH RECURSIVE cte AS 
(
SELECT array[r.term1_id, r.term2_id] AS path
FROM   temp_table r
LEFT   JOIN temp_table r0 ON r0.term1_id = r.term2_id
WHERE  r0.term1_id IS NULL
UNION ALL 
SELECT r.term1_id || c.path
FROM   cte c
JOIN   temp_table r ON r.term2_id = c.path[1]
) 
SELECT path
FROM   cte
ORDER  BY path;

结果是这样的:

"{1,5,6,1452}"
"{1,5,6,1470,1475}"

如何填充第一个数组的最后一个空格来获得这样的东西?

"{1,5,6,1452,1452}"
"{1,5,6,1470,1475}"

所以我想重复最后一个非空值,直到我覆盖每个级别。

解答:

这是一个有效的陈述

CREATE OR REPLACE FUNCTION fill_with_last_element(arr anyarray, n INTEGER)
RETURNS anyarray LANGUAGE plpgsql as $$
DECLARE
    l int = array_length(arr,1);
BEGIN
    RETURN CASE 
        WHEN l > n THEN arr 
        ELSE arr || array_fill(arr[l], array[n- l]) 
    END;
END $$;

WITH RECURSIVE cte(path) AS (
    SELECT array[r.term1_id, r.term2_id] AS path
    FROM   temp_table r
    LEFT   JOIN temp_table r0 ON r0.term1_id = r.term2_id
    WHERE  r0.term1_id IS NULL
UNION ALL 
    SELECT r.term1_id || c.path
    FROM   cte c
    JOIN   temp_table r ON r.term2_id = c.path[1]
),
max_len AS (
    SELECT max(array_length(path, 1)) max_len
    FROM cte
    )
SELECT fill_with_last_element(path, max_len)
FROM cte
CROSS JOIN max_len
ORDER BY path;

1 个答案:

答案 0 :(得分:1)

您无法生成长度相等的数组,因为在查询终止之前您不知道长度。您应该修改结果。这个功能很有用:

create or replace function fill_with_last_element(arr anyarray, n integer)
returns anyarray language plpgsql as $$
declare
    l int = array_length(arr,1);
begin
    return case 
        when l > n then arr 
        else arr || array_fill(arr[l], array[n- l]) 
    end;
end $$;

示例:

with cte(path) as (
    values
    ('{1,5,6,1452}'::int[]),
    ('{1,5,6,1470,1475}')
),
max_len as (
    select max(array_length(path, 1)) max_len
    from cte
    )
select fill_with_last_element(path, max_len)
from cte
cross join max_len

 fill_with_last_element 
------------------------
 {1,5,6,1452,1452}
 {1,5,6,1470,1475}
(2 rows)