Home >Database >Mysql Tutorial >Why are my set-returning function's columns concatenated when used in a PostgreSQL query, and how can I resolve this?

Why are my set-returning function's columns concatenated when used in a PostgreSQL query, and how can I resolve this?

Barbara Streisand
Barbara StreisandOriginal
2024-12-28 17:07:10419browse

Why are my set-returning function's columns concatenated when used in a PostgreSQL query, and how can I resolve this?

Concatenated Columns in Record Returned from Function

This issue arises when attempting to execute a query utilizing a set-returning function within another query, resulting in all function-returned columns being concatenated into a single column.

Function Declaration

The following Postgres function, account_servicetier_for_day, takes in an account ID and a day and returns historical data:

CREATE OR REPLACE FUNCTION account_servicetier_for_day(_accountid integer, _day timestamp without time zone) RETURNS setof account_dsl_history_info AS
$BODY$
DECLARE _accountingrow record;
BEGIN
  Return Query
  Select * From account_dsl_history_info
  Where accountid = _accountid And timestamp <= _day + interval '1 day - 1 millisecond'
  Order By timestamp Desc 
  Limit 1;
END;
$BODY$ LANGUAGE plpgsql;

Issue: Concatenated Columns

When the function is executed directly, it returns the expected result with separate columns. However, when used within a query, the columns are concatenated into one:

Select
    '2014-08-12' As day, 0 As inbytes, 0 As outbytes, acct.username, acct.accountid, acct.userid,
    account_servicetier_for_day(acct.accountid, '2014-08-12')
From account_tab acct
Where acct.isdsl = 1
    And acct.dslservicetypeid Is Not Null
    And acct.accountid Not In (Select accountid From dailyaccounting_tab Where Day = '2014-08-12')
Order By acct.username

Solution: SQL Decomposition

To decompose the function-returned record into individual columns, use the SQL syntax:

SELECT * FROM account_servicetier_for_day(20424, '2014-08-12');

Postgres 9.3 or Newer

For Postgres 9.3 and later, the query can be rewritten using JOIN LATERAL:

SELECT '2014-08-12' AS day, 0 AS inbytes, 0 AS outbytes
     , a.username, a.accountid, a.userid
     , f.*   -- but avoid duplicate column names!
FROM   account_tab a
     , account_servicetier_for_day(a.accountid, '2014-08-12') f  -- <-- HERE
WHERE  a.isdsl = 1
AND    a.dslservicetypeid IS NOT NULL
AND    NOT EXISTS (
   SELECT FROM dailyaccounting_tab
   WHERE  day = '2014-08-12'
   AND    accountid = a.accountid
   )
ORDER  BY a.username;

Postgres 9.2 or Older

For Postgres 9.2 or older, use a subquery to call the set-returning function and decompose the record in the outer query:

SELECT '2014-08-12' AS day, 0 AS inbytes, 0 AS outbytes
     , a.username, a.accountid, a.userid
     , (a.rec).*   -- but be wary of duplicate column names!
FROM  (
   SELECT *, account_servicetier_for_day(a.accountid, '2014-08-12') AS rec
   FROM   account_tab a
   WHERE  a.isdsl = 1
   AND    a.dslservicetypeid Is Not Null
   AND    NOT EXISTS (
       SELECT FROM dailyaccounting_tab
       WHERE  day = '2014-08-12'
       AND    accountid = a.accountid
      )
   ) a
ORDER  BY a.username;

The above is the detailed content of Why are my set-returning function's columns concatenated when used in a PostgreSQL query, and how can I resolve this?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn