Re: Set Returning Functions and joins

From: David Johnston <polobo(at)yahoo(dot)com>
To: David Greco <David_Greco(at)harte-hanks(dot)com>
Cc: "pgsql-general(at)postgresql(dot)org" <pgsql-general(at)postgresql(dot)org>
Subject: Re: Set Returning Functions and joins
Date: 2012-08-15 20:15:41
Message-ID: 6F0E1C4D-A56A-46D8-857E-278E4DA23E87@yahoo.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

On Aug 15, 2012, at 15:55, David Greco <David_Greco(at)harte-hanks(dot)com> wrote:

> I’m porting some code from an Oracle application and we have many uses of set returning function. In particular, we are using them in joins of the form:
>
> CREATE TABLE dave ( id integer, field1 integer );
> INSERT INTO dave VALUES (1, 10);
>
> SELECT
> id, g.*
> FROM
> dave
> INNER JOIN generate_series( 1, dave.field1 ) ON (1=1)
>
>
> In reality, the examples are not trivial like this, and the set returning function returns sets of records, not single values.
> Now, in the case of a LEFT JOIN and a function returning a setoff a simple value, I can rewrite it simply as:
> SELECT
> id, generate_series(1, dave.field1)
> FROM
> dave
>
>
> In the case of a LEFT JOIN and a function returning a setoff a record, I can rewrite it as:
> SELECT
> id, ( getRecord(1, dave.field1) ).*
> FROM
> dave
>
>
>
> I then figured I can rewrite INNER JOINs as:
> SELECT
> id, ( getRecord(1, dave.field1) ).*
> FROM
> dave
> WHERE
> Exists ( SELECT 1 FROM getRecord(1, dave.field1) )
>
> Though I suppose this is running getRecord once for every row in dave, then another time for every row being returned.
>
> Now in some non-trivial examples involving multiple joins on set returning functions, this gets pretty complicated.
>
>
>
>
> Is there any alternative? Or I can suggest that a query the original form should be allowed?
>
> SELECT
> id, g.*
> FROM
> dave
> INNER JOIN generate_series( 1, dave.field1 ) ON (1=1)
>

I suggest putting your function calls within a CTE (common table expression: SQL command WITH) structure.

I do not get why you think you need an "EXISTS" in the INNER JOIN situation. At worse you should make it a sub-query and add a IS NOT NULL condition on one of the function result columns. There is no way to avoid evaluating once per record in dave but you should never have to evaluate more frequently than that. CTE and sub-selects are your friends.

The original form is currently being developed but will not be available until at least 9.3

David J.

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message David Greco 2012-08-15 20:24:43 Re: Set Returning Functions and joins
Previous Message David Greco 2012-08-15 19:55:20 Set Returning Functions and joins