我有以下表格:
CREATE TABLE element (
  element_id serial PRIMARY KEY,
  local_id integer,
  name varchar,
  CONSTRAINT fk_element_local_id FOREIGN KEY (local_id)
      REFERENCES local (local_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);
CREATE TABLE local (
  local_id serial PRIMARY KEY,
  parent_id integer,
  name varchar,
  CONSTRAINT fk_local_parent_id_local_id FOREIGN KEY (parent_id)
      REFERENCES local (local_id) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE SET NULL
);
CREATE TABLE category (
  category_id serial PRIMARY KEY,
  name varchar
);
CREATE TABLE action (
  action_id serial PRIMARY KEY,
  local_id integer,
  category_id integer,
  CONSTRAINT fk_action_local_id FOREIGN KEY (local_id)
      REFERENCES local (local_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk_action_element_id FOREIGN KEY (element_id)
      REFERENCES element (element_id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
);
我想从一个动作中选择所有元素。如果元素的本地是动作的本地的后代,它也应该出现。
例子:
表local:
|local_id | parent_id | name |
|---------+-----------+------|
|1        |NULL       |A     |
|2        |1          |B     |
|3        |1          |C     |
|4        |3          |D     |
|5        |NULL       |E     |
|6        |5          |F     |
|_________|___________|______|
表category:
| category_id | name |
|-------------+------|
|1            |A     |
|2            |B     |
|2            |C     |
|_____________|______|
表element:
|element_id | local_id | name | category_id |
|-----------+----------+------+-------------|
|1          |1         |A     | 1           |
|2          |2         |B     | 2           |
|3          |2         |C     | 1           |
|4          |4         |D     | 2           |
|5          |5         |E     | 2           |
|6          |6         |F     | 1           |
|7          |6         |G     | 1           |
|___________|__________|______|_____________|
表action:
|action_id | local_id | category_id |
|----------+----------+-------------|
| 1        | 1        | 2           |
| 2        | 3        | 1           |
| 3        | 5        | 1           |
| 4        | 6        | 1           |
|__________|__________|_____________|
我想要的查询结果:
CASE: action_id = 1
return: element_id: 2,4
CASE: action_id = 2
return: element_id: null
CASE: action_id = 3
return: element_id: 6,7
我已经创建了一个函数,它返回包括实际节点在内的所有后代,但由于调用函数数千次时的性能,我遇到了困难。我的功能如下所示:
CREATE OR REPLACE FUNCTION fn_local_get_childs(_parent_id integer)
  RETURNS SETOF integer AS
$BODY$
DECLARE
   r integer;
BEGIN
   FOR r IN SELECT local_id FROM local WHERE local_id IN ( 
      (WITH RECURSIVE parent AS
      (
         SELECT local_id , parent_id  from local WHERE local_id = _parent_id
         UNION ALL 
         SELECT t.local_id , t.parent_id FROM parent
         INNER JOIN local t ON parent.local_id =  t.parent_id
      )
      SELECT local_id FROM  parent
      ) 
   )
   LOOP
      RETURN NEXT r;
   END LOOP;
   RETURN;        
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;
我的超慢查询如下所示:
select e.element_id, a.action_id
from action a
join element e on (
                   e.local_id=any(select fn_local_get_childs(a.local_id)) AND 
                   e.category_id=a.category_id)
有没有办法在单个查询中组合函数中使用的递归?