gpt4 book ai didi

sql - 将递归函数转换为 View

转载 作者:行者123 更新时间:2023-11-29 11:24:49 24 4
gpt4 key购买 nike

我正在尝试将 Postgres 中的函数转换为 select我打算用作 View 的查询。原因是我想通过 select 从客户端访问它用 where 查询子句而不是像函数那样使用参数。该表表示一棵树(和邻接表),定义如下:

CREATE TABLE tree (
id serial primary key,
parent_id int references tree(id)
);

INSERT INTO tree (id, parent_id) VALUES
(1,null)
, (2,1), (3,2), (4,3), (5,3)
, (6,5), (7,6), (8,4), (9,8)
, (10,9), (11,9), (12,7)
, (13,12), (14,12), (15,11)
, (16,15), (17,16), (18,14)
, (19,13), (20,19), (21,20);

SELECT setval ('tree_id_seq', 21); -- reset sequence

-- This produces a tree like:
-- +-- <10>
-- /
-- +-- <4> -- <8> --- <9> -+- <11> --- <15> --- <16> --- <17>
-- /
-- <1> --- <2> --- <3> -+
-- \
-- +-- <5> --- <6> --- <7> --- <12> -+- <14> --- <18>
-- \
-- \
-- \
-- \
-- +-- <13> --- <19> --- <20> --- <21>
--

为了按顺序获得从树中的任何节点到根的路径,我使用了这个函数:

create or replace function _tree(rev int)
returns table(id int, parent_id int, depth int) as $$
declare
sql text;
begin
sql = 'WITH RECURSIVE tree_list(id, parent_id, depth) AS (
SELECT id, parent_id, 1 FROM tree WHERE id = ' || rev ||
'UNION
SELECT p.id, p.parent_id, r.depth + 1
FROM tree p, tree_list r
WHERE p.id = r.parent_id
)
SELECT id, parent_id, depth FROM tree_list order by id;';
return query execute sql;
end;
$$ language plpgsql;

查询看起来像 select * from _tree(15) .问题是我如何将这个函数转换成一个 View ,这样我就可以调用 select * from tree where id <= 15 .此外, View 是否会以与函数相同的速度执行(即 where 子句是否会被视为执行查询时)?

最佳答案

更简单的功能

首先,您可以大大简化您的函数。这个更简单的 SQL 函数执行相同的操作:

CREATE OR REPLACE FUNCTION f_tree(_rev int)
RETURNS TABLE(id int, parent_id int, depth int) AS
$func$
WITH RECURSIVE tree_list AS (
SELECT t.id, t.parent_id, 1 -- AS depth
FROM tree t
WHERE t.id = $1

UNION ALL -- no point using UNION
SELECT t.id, t.parent_id, r.depth + 1
FROM tree_list r
JOIN tree t ON t.id = r.parent_id
)
SELECT t.id, t.parent_id, t.depth
FROM tree_list t
ORDER BY t.id;
$func$ LANGUAGE sql;

调用:

select * from f_tree(15);
  • 可以使用 plpgsql,在 PostgreSQL 9.2 之前的版本中可能稍微有利于兑现查询计划。但是您在没有必要的情况下使用动态 SQL 使唯一的理论上的好处付之东流。这根本没有意义。简化为纯 SQL。

  • 使用 UNION ALL 而不是 UNION,因为不会有设计上的欺骗,所以更便宜。

只是 SQL

显然,您可以将其替换为纯 SQL:

WITH RECURSIVE tree_list AS (
SELECT t.id, t.parent_id, 1 AS depth
FROM tree t
WHERE t.id = 15 -- enter parameter here

UNION ALL
SELECT t.id, t.parent_id, r.depth + 1
FROM tree_list r
JOIN tree t ON t.id = r.parent_id
)
SELECT t.id, t.parent_id, t.depth
FROM tree_list t
ORDER BY t.id;

做同样的事。

查看

现在,VIEW 是一件小事:

CREATE OR REPLACE VIEW v_tree15 AS
WITH RECURSIVE tree_list AS (
SELECT t.id, t.parent_id, 1 AS depth
FROM tree t
WHERE t.id <= 15 -- only detail to change

UNION ALL
SELECT t.id, t.parent_id, r.depth + 1
FROM tree_list r
JOIN tree t ON t.id = r.parent_id
)
SELECT t.id, t.parent_id, t.depth
FROM tree_list t
ORDER BY t.id;

结果对我来说意义不大,但是这个问题没有定义任何更明智的东西..

关于sql - 将递归函数转换为 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13391457/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com