From: | "W(dot) Trevor King" <wking(at)tremily(dot)us> |
---|---|
To: | pgsql-general(at)postgresql(dot)org |
Subject: | Dynamically filtering a CTE? |
Date: | 2018-04-20 00:00:55 |
Message-ID: | 20180420000055.GL27577@valgrind.us |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general |
I have a slow ‘WITH RECURSIVE’ CTE like:
CREATE VIEW ancestors AS
WITH RECURSIVE _ancestors(descendant, ancestors) AS (
SELECT
item.id AS id,
ARRAY[item.ancestor_id] AS ancestors
FROM items AS item
UNION ALL
SELECT
child.id AS id
child.ancestors || ancestor.ancestor_id AS ancestors
FROM _ancestors AS child
JOIN items as ancestor
ON child.ancestors[array_length(child.ancestors, 1)] = ancestor.id
)
SELECT *
FROM _ancestors
WHERE child.ancestors[array_length(child.ancestors, 1)] IS NULL;
I'll usually only need a few rows, so I'm being bitten by PostgreSQL's
CTE optimization fence [1]. I'm looking to optimize it by limiting
the dynamically limiting the number of rows in the initial query, as
if it had been:
WITH RECURSIVE _ancestors(id, ancestors) AS (
SELECT
item.id AS id,
ARRAY[item.ancestor_id] AS ancestors
FROM items AS item
WHERE {your condition here}
UNION ALL
…
)
My initial thought was to create a function which accepted a WITH
clause as an argument. Something like:
CREATE OR REPLACE FUNCTION ancestors(condition)
RETURNS TABLE(id integer, ancestors integer[]) AS
$$
WITH RECURSIVE _ancestors(id, ancestors) AS (
SELECT
item.id AS id,
ARRAY[item.ancestor_id] AS ancestors
FROM items AS item
WHERE condition
UNION ALL
…
)
…
$$ LANGUAGE SQL;
or with ‘WHERE condition(item)’. But I couldn't find a way to define
an argument that was a where condition [2] or a record→boolean
function [3]. I could probably use PREPARE/EXECUTE [4] to dynamically
construct the WHERE statement, but that looks like it may have its own
optimization issues and there's no way to stash it for use in
subsequent sessions. Perhaps a function to run the PREPARE? Is there
an idiomatic way to approach this problem?
Thanks,
Trevor
[1]: https://www.postgresql.org/message-id/201209191305.44674.db@kavod.com
[2]: https://www.postgresql.org/docs/10/static/sql-select.html#SQL-WHERE
[3]: https://www.postgresql.org/docs/10/static/sql-createfunction.html
[4]: https://www.postgresql.org/docs/10/static/sql-prepare.html
--
This email may be signed or encrypted with GnuPG (http://www.gnupg.org)
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy
From | Date | Subject | |
---|---|---|---|
Next Message | David G. Johnston | 2018-04-20 00:28:00 | Re: Dynamically filtering a CTE? |
Previous Message | Ken Tanzer | 2018-04-19 23:35:35 | Re: Problem with trigger makes Detail record be invalid |