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
Release: 2024-12-28 17:07:10
Original
416 people have browsed it

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;
Copy after login

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
Copy after login

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');
Copy after login

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;
Copy after login

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;
Copy after login

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!

source:php.cn
Statement of this Website
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
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template