1

次のデータがある(空白はNULLを意味します):

ID    ColA    ColB    ColC
1     15              20
2     11      4       
3             3

単一のクエリで各列の最後のNULL以外の値を取得するにはどうすればよいですか?したがって、指定されたデータの結果は次のようになります。

ColA    ColB    ColC
11      3       20

私が説明したのと同じようなことをしているように見える関数はあまり見つかりCOALESCEませんでしたが、私の場合は期待どおりに機能しません。

4

2 に答える 2

1

サブクエリを使用できます。

select
  (select ColA from TheTable where ColA is not null order by ID desc limit 1) as ColA,
  (select ColB from TheTable where ColB is not null order by ID desc limit 1) as ColB,
  (select ColC from TheTable where ColC is not null order by ID desc limit 1) as Col
于 2012-11-12T16:36:16.683 に答える
1

プレーンSQLを使用して列ごとに個別のクエリを実行する必要があるようです。小さなテーブルで3列しかない場合は、@Guffaのクエリで問題ありません。

3つのウィンドウ関数

3つのウィンドウ関数を使用して1つのクエリで同じことを行うことができます。これが3つの個別のサブクエリよりも高速かどうかはわかりません。

SELECT first_value(cola) OVER (ORDER BY cola IS NULL, id DESC) AS cola
      ,first_value(colb) OVER (ORDER BY colb IS NULL, id DESC) AS colb
      ,first_value(colc) OVER (ORDER BY colc IS NULL, id DESC) AS colc
FROM   tbl
LIMIT  1;

count()ウィンドウ関数として

count()値をカウントしないという事実を利用することもできNULLます。

WITH x AS (
   SELECT CASE WHEN count(cola) OVER w = 1 THEN cola ELSE NULL END AS cola
         ,CASE WHEN count(colb) OVER w = 1 THEN colb ELSE NULL END AS colb
         ,CASE WHEN count(colc) OVER w = 1 THEN colc ELSE NULL END AS colc
   FROM   tbl
   -- WHERE id > x -- safe to ignore a certain portion from a large table?
   WINDOW w AS (ORDER  BY id DESC)
   )
SELECT max(cola) AS cola, max(colb) AS colb, max(colc) AS colc
FROM   x

より大きなテーブルとより多くの列の場合、再帰CTEまたは手続き型関数はかなり高速になります。

再帰CTE

WITH RECURSIVE x AS (
   SELECT cola, colb, colc
         ,row_number() OVER (ORDER  BY id DESC) AS rn
   FROM   tbl
   )

   , y AS (
   SELECT rn, cola, colb, colc
   FROM   x
   WHERE  rn = 1

   UNION ALL
   SELECT x.rn
        , COALESCE(y.cola,x.cola)
        , COALESCE(y.colb,x.colb)
        , COALESCE(y.colc,x.colc)
   FROM   y
   JOIN   x ON  x.rn = y.rn + 1
   WHERE  y.cola IS NULL OR y.colb IS NULL OR y.colc IS NULL
   )
SELECT cola, colb, colc
FROM   y
ORDER  BY rn DESC
LIMIT  1;

PL/pgSQL関数

私のお金は最高のパフォーマンスのためにこれにあります:

CREATE OR REPLACE FUNCTION f_last_nonull(OUT cola int
                                       , OUT colb int
                                       , OUT colc int) AS
$func$
DECLARE
   r record;
BEGIN

FOR r IN
   SELECT t.cola, t.colb, t.colc 
   FROM   tbl t
   ORDER  BY t.id DESC
LOOP
   IF cola IS NULL AND r.cola IS NOT NULL THEN cola := r.cola; END IF;
   IF colb IS NULL AND r.colb IS NOT NULL THEN colb := r.colb; END IF;
   IF colc IS NULL AND r.colc IS NOT NULL THEN colc := r.colc; END IF;

   EXIT WHEN NOT (cola IS NULL OR colb IS NULL OR colc IS NULL);
END LOOP;

END
$func$ LANGUAGE plpgsql;

電話:

SELECT * FROM f_last_nonull();
cola | colb | colc
-----+------+------
 11  | 3    | 20

でテストしEXPLAIN ANALYZEます。ソリューションの比較をして戻ってきていただければ幸いです。

于 2012-11-12T17:37:47.847 に答える