Re: converting in() clause into a with prefix? - Mailing list pgsql-general

From David G. Johnston
Subject Re: converting in() clause into a with prefix?
Date
Msg-id CAKFQuwb5t=xag+KGtXEpFn=poxCGS=FTqOnPQzcSzaeYCgBJww@mail.gmail.com
Whole thread Raw
In response to converting in() clause into a with prefix?  (Benjamin Smith <lists@benjamindsmith.com>)
List pgsql-general
On Fri, Oct 16, 2015 at 2:18 PM, Benjamin Smith <lists@benjamindsmith.com> wrote:
I have a horribly-performing query similar to below, and I'd like to convert
it to use a "WITH mytable as ( ... ) " without having to re-architect my code.
For some reason, using a WITH prefix seems to generally work much faster than
IN() sub clause even allowing identical results. (runs in 1/4th the time)

Is there a PG native function that can convert the listing format of in()
clause to row-level results from a WITH prefix? I see the array* functions but
they seem to work with arrays like "array[1,2,3]" and unnest seems to drill
right through nested arrays and flattens every single element to a new row,
regardless of depth.  EG: the following two lines are equivalent:

select unnest(array([1,2,2,3]);
select unnest(array[array[1,2],array[2,3]]);

I'd expect the latter to put out two rows as

1, 2
2, 3

Thanks for your input, clarifying pseudo code examples below (PHP). We're
running 9.4.4 on CentOS 6.

Ben


// DESIRED END RESULT PSUEDO CODE
$query = "
WITH mytable AS
        (
        unnest(". $in .", school_id, building_id)
        )
SELECT
        id,
        name
FROM mytable
JOIN classes ON
        (
        mytable.school_id = classes.school_id
        AND mytable.building_id = classes.building_id
        )" ;


// CURRENT CODE EXAMPLE (PHP)
$query = "
SELECT
        id,
        name
FROM classes
WHERE
        (classes.school_id, classes.building_id) IN (" . $in . ")";


// EXAMPLE RESULT (small list)
SELECT
        id,
        name
FROM classes
WHERE
        (classes.school_id, classes.building_id) IN ((291,189),(291,192),
​[...]​


 
​WITH input_table AS (​
 SELECT
 split_part(input_as_table, ',', 1) AS col1,
 split_part(input_as_table, ',', 2) AS col2
  FROM 
regexp_split_to_table(
​    ​
substring('(1,2),(3,4)', 2, 11-2),
​  -- 11 = length of input string​
​    ​
 '\),\('
) AS input_as_table 
)

pgsql-general by date:

Previous
From: Benjamin Smith
Date:
Subject: converting in() clause into a with prefix?
Next
From: dinesh kumar
Date:
Subject: Re: converting in() clause into a with prefix?