2016-09-12 6 views
0

Это SQL-запрос я использовал, чтобы получить данные из моей таблицы, которая содержит родитель-потомок значения:заполнить пустое пространство на рекурсивном 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

Вы не можете создавать массивы с одинаковой длиной, потому что вы не знаете длину до запроса завершается. Вы должны изменить результаты. Эта функция будет полезна:

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) 
+0

Именно то, что мне нужно! Огромное спасибо! – xCloudx8