Search Postgresql Archives

Re: Seamless replacement to MySQL's GROUP_CONCAT function...

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



That is good and I will effect that change here; but as far as I can see
you will still need to permute the types of the arguments in that set of
functions in order for the aggregates to accept an int argument and an
optional text argument, and zap out a TEXT...

========================
On 08/06/2013 12:49 AM, Pavel Stehule wrote:
> Hello
>
> 2013/8/3 immersive.excel@xxxxxxxxx <immersive.excel@xxxxxxxxx>:
>> I needed a GROUP_CONCAT to port some queries to postgres.
>>
>> In discussions online, I found repeated advice for rewriting the queries,
>> but no solid way to formulate the GROUP_CONCAT as a postgres function.
>> Rewrite perhaps hundreds of queries that happen to be in the app you're
>> porting? Puh-lease!
>>
>> Note: I found some close-but-no cigar aggregates shared online, but they
>> would not accept integer arguments, nor would they handle the optionally
>> furnished delimiter. People would suggesting casting the argument to the
>> pseudo-GROUP_CONCAT. Again: Rewrite perhaps hundreds of queries?
>>
>> And now the formulation of GROUP_CONCAT for postgres that accepts either
>> integer or string columns, and the optional delimiter:
>>
>> -- permutation of GROUP_CONCAT parameter types with delimiter parameter
>> furnished:
>> CREATE OR REPLACE
>> FUNCTION GROUP_CONCAT_ATOM(field1 TEXT, field2 TEXT, delimiter TEXT)
>>          RETURNS TEXT AS $$
>> BEGIN
>> IF field1 IS NULL THEN
>>    RETURN field2;
>> ELSIF field2 IS NULL THEN
>>       RETURN field1;
>> ELSE
>>      RETURN field1||delimiter||field2;
>> END IF;
>> END;
>> $$ LANGUAGE plpgsql;
> your code will be significantly faster when you don't use a classic C
> programming style and use a COALESCE function. PL/pgSQL is a
> interpreted language and is necessary to minimize number of
> instruction.
>
> you code can be translated to
>
> CREATE OR REPLACE
> FUNCTION GROUP_CONCAT_ATOM(field1 TEXT, field2 TEXT, delimiter TEXT)
>          RETURNS TEXT AS $$
> BEGIN
>   RETURN COALESCE(field1||delimiter||field2, field2, field1);
> END;
> $$ LANGUAGE plpgsql;
>
> Regards
>
> Pavel
>
> p.s. speed is in this use case important, because you execute this
> function for every row
>
>
>> CREATE OR REPLACE
>> FUNCTION GROUP_CONCAT_ATOM(field1 TEXT, field2 INT8, delimiter TEXT)
>>          RETURNS TEXT AS $$
>> BEGIN
>> IF field1 IS NULL THEN
>>    IF field2 IS NULL THEN
>>       RETURN NULL;
>>    ELSE
>>         RETURN CAST(field2 AS TEXT);
>>    END IF;
>> ELSIF field2 IS NULL THEN
>>       RETURN field1;
>> ELSE
>>      RETURN field1||delimiter||CAST(field2 AS TEXT);
>> END IF;
>> END;
>> $$ LANGUAGE plpgsql;
>>
>> CREATE OR REPLACE
>> FUNCTION GROUP_CONCAT_ATOM(field1 INT8, field2 TEXT, delimiter TEXT)
>>          RETURNS TEXT AS $$
>> BEGIN
>> IF field1 IS NULL THEN
>>    RETURN field2;
>> ELSIF field2 IS NULL THEN
>>       IF field1 IS NULL THEN
>>          RETURN NULL;
>>       ELSE
>>            RETURN CAST(field1 AS TEXT);
>>       END IF;
>> ELSE
>>      RETURN CAST(field1 AS TEXT)||delimiter||field2;
>> END IF;
>> END;
>> $$ LANGUAGE plpgsql;
>>
>> CREATE OR REPLACE
>> FUNCTION GROUP_CONCAT_ATOM(field1 INT8, field2 INT8, delimiter TEXT)
>>          RETURNS TEXT AS $$
>> BEGIN
>> IF field1 IS NULL THEN
>>    IF field2 IS NULL THEN
>>       RETURN NULL;
>>    ELSE
>>         RETURN CAST(field2 AS TEXT);
>>    END IF;
>> ELSIF field2 IS NULL THEN
>>       IF field1 IS NULL THEN
>>          RETURN NULL;
>>       ELSE
>>            RETURN CAST(field1 AS TEXT);
>>       END IF;
>> ELSE
>>      RETURN CAST(field1 AS TEXT)||delimiter||CAST(field2 AS TEXT);
>> END IF;
>> END;
>> $$ LANGUAGE plpgsql;
>>
>> -- permutation of function arguments without delimiter furnished:
>> CREATE OR REPLACE
>> FUNCTION GROUP_CONCAT_ATOM(field1 TEXT, field2 TEXT) -- delimiter=','
>>          RETURNS TEXT AS $$
>> BEGIN
>> IF field1 IS NULL THEN
>>    IF field2 IS NULL THEN
>>       RETURN NULL;
>>    ELSE
>>         RETURN CAST(field2 AS TEXT);
>>    END IF;
>> ELSIF field2 IS NULL THEN
>>       RETURN field1;
>> ELSE
>>      RETURN field1||','||field2;
>> END IF;
>> END;
>> $$ LANGUAGE plpgsql;
>>
>> CREATE OR REPLACE
>> FUNCTION GROUP_CONCAT_ATOM(field1 INT8, field2 INT8) -- delimiter=','
>>          RETURNS TEXT AS $$
>> BEGIN
>> IF field1 IS NULL THEN
>>    IF field2 IS NULL THEN
>>       RETURN NULL;
>>    ELSE
>>         RETURN CAST(field2 AS TEXT);
>>    END IF;
>> ELSIF field2 IS NULL THEN
>>       IF field1 IS NULL THEN
>>          RETURN NULL;
>>       ELSE
>>            RETURN CAST(field1 AS TEXT);
>>       END IF;
>> ELSE
>>      RETURN CAST(field1 AS TEXT)||','||CAST(field2 AS TEXT);
>> END IF;
>> END;
>> $$ LANGUAGE plpgsql;
>>
>> CREATE OR REPLACE
>> FUNCTION GROUP_CONCAT_ATOM(field1 INT8, field2 TEXT)
>>          RETURNS TEXT AS $$
>> BEGIN
>> IF field1 IS NULL THEN
>>    RETURN field2;
>> ELSIF field2 IS NULL THEN
>>       IF field1 IS NULL THEN
>>          RETURN NULL;
>>       ELSE
>>            RETURN CAST(field1 AS TEXT);
>>       END IF;
>> ELSE
>>      RETURN CAST(field1 AS TEXT)||','||field2;
>> END IF;
>> END;
>> $$ LANGUAGE plpgsql;
>>
>> CREATE OR REPLACE
>> FUNCTION GROUP_CONCAT_ATOM(field1 TEXT, field2 INT8) -- delimiter=','
>>          RETURNS TEXT AS $$
>> BEGIN
>> IF field1 IS NULL THEN
>>    IF field2 IS NULL THEN
>>       RETURN NULL;
>>    ELSE
>>         RETURN CAST(field2 AS TEXT);
>>    END IF;
>> ELSIF field2 IS NULL THEN
>>       RETURN field1;
>> ELSE
>>      RETURN field1||','||CAST(field2 AS TEXT);
>> END IF;
>> END;
>> $$ LANGUAGE plpgsql;
>>
>> -- aggregates for all parameter types with delimiter:
>> DROP AGGREGATE IF EXISTS GROUP_CONCAT(TEXT, TEXT); -- field, delimiter
>> CREATE AGGREGATE GROUP_CONCAT(TEXT, TEXT) -- field, delimiter
>>                  (SFUNC=GROUP_CONCAT_ATOM,
>>                   STYPE=TEXT
>>                  );
>>
>> DROP AGGREGATE IF EXISTS GROUP_CONCAT(INT8, TEXT); -- field, delimiter
>> CREATE AGGREGATE GROUP_CONCAT(INT8, TEXT) -- field, delimiter
>>                  (SFUNC=GROUP_CONCAT_ATOM,
>>                   STYPE=TEXT
>>                  );
>>
>> -- aggregates for all parameter types without the optional delimiter:
>> DROP AGGREGATE IF EXISTS GROUP_CONCAT(TEXT); -- field, delimiter=','
>> CREATE AGGREGATE GROUP_CONCAT(TEXT) -- field
>>                  (SFUNC=GROUP_CONCAT_ATOM,
>>                   STYPE=TEXT
>>                  );
>>
>> DROP AGGREGATE IF EXISTS GROUP_CONCAT(INT8); -- field, delimiter=','
>> CREATE AGGREGATE GROUP_CONCAT(INT8) -- field
>>                  (SFUNC=GROUP_CONCAT_ATOM,
>>                   STYPE=TEXT
>>                  );
>>



-- 
Sent via pgsql-general mailing list (pgsql-general@xxxxxxxxxxxxxx)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Postgresql Jobs]     [Postgresql Admin]     [Postgresql Performance]     [Linux Clusters]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Postgresql & PHP]     [Yosemite]
  Powered by Linux