マルチコラムサブQueriesを使用して、行のポストグレスバルクアップデート

StackOverflow https://stackoverflow.com/questions/8890492

質問

親テーブルの6フィールドの子テーブルからの要約値(カウント、最小、最大)でテーブル(親テーブル)のすべての行を更新する必要があります

tab1 (parent table)
-------------------
tab1_ID 
tab1_low
tab1_high
tab2_ref_count
tab2_ref_low
tab2_ref_high
tab3_ref_count
tab3_ref_low
tab3_ref_high
STUS_CD

tab2 (link table for tab1 to tab1)
----------------------------------
tab1_ID
tab1_ref_ID

tab3 (link table for tab1 to tab4)
----------------------------------
tab1_ID
tab4_ref_ID

tab4
-----
tab4_ID
tab4_low
tab4_high

Tab2とTab3のカウントをTab1にロールアップするには、以下が私が試みているクエリです -

UPDATE tab1
SET    (tab2_ref_count, tab2_ref_low, tab2_ref_high)  = 
                     (SELECT COUNT(t1.tab1_ID), MIN(t1.tab1_low),     MAX(t1.tab1_high)
                      FROM   tab2 t2 JOIN tab1 t1 ON (t2.tab1_ref_ID =     t1.tab1_ID) 
                      WHERE  tab1.tab1_ID = t2.tab1_ID),
       (tab3_ref_count, tab3_ref_low, tab3_ref_high)  = 
                     (SELECT COUNT(t4.tab4_ID), MIN(t4.tab4_low),       MAX(t4.tab4_high)
                      FROM   tab3 t3 JOIN tab4 t4 ON (t3.tab4_ref_ID =     t4.tab4_ID)
                      WHERE  tab1.tab1_ID = t3.tab1_ID)
WHERE  STUS_CD IN ('01','02')

しかし、どうやらそれは機能していません。ヒントはありますか?

役に立ちましたか?

解決

このように機能する可能性があります:

UPDATE tab1 t1
SET    tab2_ref_count = t2.ct
     , tab2_ref_low   = t2.low
     , tab2_ref_high  = t2.high
     , tab3_ref_count = t3.ct
     , tab3_ref_low   = t3.low
     , tab3_ref_high  = t3.high
FROM  (
    SELECT t2.tab1_id
         , count(*)          AS ct
         , min(t1.tab1_low)  AS low
         , max(t1.tab1_high) AS high
    FROM  tab2 t2
    JOIN  tab1 t1 ON t1.tab1_id = t2.tab1_ref_id 
    GROUP BY 1
    ) t2
JOIN  (
    SELECT t3.tab1_id
         , count(*)          AS ct
         , min(t4.tab1_low)  AS low
         , max(t4.tab1_high) AS high
    FROM   tab3 t3
    JOIN   tab4 t4 ON t4.tab4_id = t3.tab4_ref_id 
    GROUP  BY 1
    ) t3 USING (tab1_id)
WHERE  stus_cd IN ('01','02')
AND    t1.tab1_id = t2.tab1_id;
-- AND    t1.tab1_id = COALESCE(t2.tab1_id, t3.tab1_id);  .. for FULL OUTER JOIN

主要なポイント:

  • 私が使う count(*) それ以外の count(t4.tab1_id). 。ここでは同じ結果が保証されていますが、よりシンプルで速いです。

  • クエリは、行があることを前提としています tab3 すべてのための tab1_id それがあります tab2, 、 それも。そうでない場合は、 JOIN タイプに LEFT JOIN また FULL OUTER JOIN. 。この場合の最終Where句で提供された代替案を使用します。

  • このクエリは行を更新しません tab1 まったく、関係していない場合はどちらにもあります tab2 また tab3.

他のヒント

PostgreSQLは、更新ステートメントでタプルの定義をサポートしていません(しかし、計画されていると思います)

このようなものを使用できます(テストされていません):

UPDATE tab1
  SET tab2_ref_count = tt1.tab1_id_count, 
      tab2_ref_low = tt1.tab1_low_min, 
      tab2_ref_high = tt1.tab1_high_max
FROM (
     SELECT COUNT(t1.tab1_ID) as tab1_id_count, 
            MIN(t1.tab1_low) as tab1_low_min,     
            MAX(t1.tab1_high) as tab1_high_max
     FROM  tab2 t2 
     JOIN tab1 t1 ON (t2.tab1_ref_ID = t1.tab1_ID) 
     WHERE  tab1.tab1_ID = t2.tab1_ID
 ) tt1
 ....
 WHERE  STUS_CD IN ('01','02')

(どこ ... 例の2番目のサブセレクトの2番目の派生テーブルを示します)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top