Rumah >pangkalan data >tutorial mysql >Mengapakah lajur fungsi pengembalian set saya digabungkan apabila digunakan dalam pertanyaan PostgreSQL, dan bagaimana saya boleh menyelesaikannya?

Mengapakah lajur fungsi pengembalian set saya digabungkan apabila digunakan dalam pertanyaan PostgreSQL, dan bagaimana saya boleh menyelesaikannya?

Barbara Streisand
Barbara Streisandasal
2024-12-28 17:07:10419semak imbas

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

Lajur Bercantum dalam Rekod Dikembalikan daripada Fungsi

Isu ini timbul apabila cuba melaksanakan pertanyaan menggunakan fungsi pengembalian set dalam pertanyaan lain, menyebabkan semua fungsi dikembalikan lajur disatukan menjadi satu lajur.

Fungsi Pengisytiharan

Fungsi Postgres berikut, account_servicetier_for_day, mengambil ID akaun dan sehari dan mengembalikan data sejarah:

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;

Isu: Lajur Bercantum

Apabila fungsi itu dilaksanakan secara langsung, ia mengembalikan hasil yang dijangkakan dengan lajur yang berasingan. Walau bagaimanapun, apabila digunakan dalam pertanyaan, lajur disatukan menjadi satu:

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

Penyelesaian: Penguraian SQL

Untuk menguraikan rekod yang dikembalikan fungsi ke dalam lajur individu, gunakan sintaks SQL:

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

Postgres 9.3 atau Lebih Baru

Untuk Postgres 9.3 dan lebih baru, pertanyaan boleh ditulis semula menggunakan 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 atau Lebih Lama

Untuk Postgres 9.2 atau lebih lama, gunakan subquery untuk memanggil fungsi set-returning dan menguraikan rekod dalam pertanyaan luar:

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;

Atas ialah kandungan terperinci Mengapakah lajur fungsi pengembalian set saya digabungkan apabila digunakan dalam pertanyaan PostgreSQL, dan bagaimana saya boleh menyelesaikannya?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn