복붙노트

[SQL] 함수에서 반환 녹음 열이 연결된했다

SQL

함수에서 반환 녹음 열이 연결된했다

나는 상점은 시간이 지남에 따라 변경 계정 테이블이있다. 나는 그 기록이 존재하지 않는 경우, 특정 일에 대한 몇 가지 기록을 만들기 위해 두 테이블이를 가입해야합니다.

(I 희망) 일을 더 쉽게하기 위해, 나는 쿼리를 캡슐화 한 그 계정 ID를받는 함수, 하루에 반환 정확한 기록 데이터를.

내가 실행하면 "* account_servicetier_for_day 선택 (20,424를, '2014년 8월 12일')", 나는 예상 된 결과 (별도의 컬럼에 함수에서 반환 된 모든 데이터)를 얻는다. 내가 다른 쿼리 내에서 기능을 사용하는 경우, 나는 하나에 합류 모든 열을 얻을 :

("2014-08-12 14:20:37",hollenbeck,691,12129,20424,69.95,"2Mb/1Mb 20GB Limit",2048,1024,20.000)

나는 "GCC (GCC)에 의해 컴파일 x86_64에-슬랙웨어 - 리눅스 GNU에 PostgreSQL을 9.2.4, 4.7.1, 64 비트"를 사용하고 있습니다.

질문:

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

함수:

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;

해결법

  1. ==============================

    1.일반적으로, 함수에서 반환 된 행을 분해하고 개별 열을 얻을 수 있습니다 :

    일반적으로, 함수에서 반환 된 행을 분해하고 개별 열을 얻을 수 있습니다 :

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

    쿼리에 관해서는 :

    와 클리너 측면 가입 :

    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 1
       FROM   dailyaccounting_tab
       WHERE  day = '2014-08-12'
       AND    accountid = a.accountid
       )
    ORDER  BY a.username;
    

    측면 키워드는 기능이 항상 항목 FROM 이전 참조 할 수 있습니다, 여기에 암시 적이다. 수동 :

    관련 :

    목록에서의 쉼표로 짧은 표기법 (주로) 간 동등의 결과를 함수 호출이 리턴없이 열로부터 따라서 제거 행 ([INNER]가 ON TRUE ... 횡 가입 동일) 측면 조인. 이러한 행을 유지하려면 사용 왼쪽 측면 ... ON TRUE 가입 :

    ...
    FROM  account_tab a
    LEFT  JOIN LATERAL account_servicetier_for_day(a.accountid, '2014-08-12') f ON TRUE
    ...
    

    또한, 사용하지 않는 NOT IN (하위 쿼리) 당신이 그것을 피할 수 있습니다 때. 그것은 그렇게하는 방법에는 여러 가지의 느린 가장 까다로운 :

    나는 NOT 대신 EXISTS 좋습니다.

    당신은 (표준 SQL의 포스트 그레스 확장이다) SELECT 목록의 집합을 돌려주는 함수를 호출 할 수 있습니다. 성능상의 이유로이 가장 하위 쿼리에서 이루어집니다. 함수의 평가 반복을 방지하기 위해 외부 질의에 (! 잘 알려진) 열 타입 분해 :

    SELECT '2014-08-12' AS day, 0 AS inbytes, 0 AS outbytes
         , a.username, a.accountid, a.userid
         , (a.rec).*   -- but avoid 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 1
           FROM   dailyaccounting_tab
           WHERE  day = '2014-08-12'
           AND    accountid = a.accountid
          )
       ) a
    ORDER  BY a.username;
    

    우리는 더 나은 외부 쿼리에서 분해하는 이유에 대한 설명, 크레이그 벨소리로 관련 대답 :

    SELECT 목록 포스트 그레스 10 결국 다시 구현 집합을 반환하는 함수는 예기치 않은 부작용을 해결한다.

  2. ==============================

    2.로부터 절에서 함수를 사용하여

    로부터 절에서 함수를 사용하여

    Select
        '2014-08-12' As day,
        0 As inbytes,
        0 As outbytes,
        acct.username,
        acct.accountid,
        acct.userid,
        asfd.*
    From
        account_tab acct
        cross join lateral
        account_servicetier_for_day(acct.accountid, '2014-08-12') asfd
    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
    
  3. from https://stackoverflow.com/questions/25392371/record-returned-from-function-has-columns-concatenated by cc-by-sa and MIT license