戻り値がnullの場合、postgresqlは0を返します


99

avg(price)を返すクエリがあります

  select avg(price)
  from(
      select *, cume_dist() OVER (ORDER BY price desc) from web_price_scan
      where listing_Type='AARM'
        and u_kbalikepartnumbers_id = 1000307
        and (EXTRACT(Day FROM (Now()-dateEnded)))*24 < 48
        and price>( select avg(price)* 0.50
                    from(select *, cume_dist() OVER (ORDER BY price desc)
                         from web_price_scan
                         where listing_Type='AARM'
                           and u_kbalikepartnumbers_id = 1000307
                           and (EXTRACT(Day FROM (Now()-dateEnded)))*24 < 48
                        )g
                   where cume_dist < 0.50
                 )
        and price<( select avg(price)*2
                    from( select *, cume_dist() OVER (ORDER BY price desc)
                          from web_price_scan
                          where listing_Type='AARM'
                            and u_kbalikepartnumbers_id = 1000307
                            and (EXTRACT(Day FROM (Now()-dateEnded)))*24 < 48
                        )d
                    where cume_dist < 0.50)
     )s

  having count(*) > 5

使用できる値がない場合に0を返す方法


1
あなたはクエリが整形式であると確信していますか?
Luc M

2
@LucM:整形式のクエリにすることはできません。(「group by」句のない「having」句。)
Mike Sherrill 'Cat Recall'

すべてが正常に機能しますが、ルールが満たされない場合は何も返されないことがあります。加えて、平均してどうやって腐敗するのでしょうか。それは不可能だと思います||要点は?複数の選択from web_price_scanは個別の選択です。ここで何が問題なのかわかりませんか?
Andrew

a havingなしの句を使用しても問題ありませんgroup by(デフォルトでは単一のグループになります)。where集計結果の条項として機能します。この場合、第1レベルのサブクエリによって5行を超える行が返された場合にのみ、行が返されます。
bruceskyaus

回答:


177

合体を使用する

COALESCE(value [, ...])
The COALESCE function returns the first of its arguments that is not null.  
Null is returned only if all arguments are null. It is often
used to substitute a default value for null values when data is
retrieved for display.

編集する

COALESCEクエリの例を次に示します。

SELECT AVG( price )
FROM(
      SELECT *, cume_dist() OVER ( ORDER BY price DESC ) FROM web_price_scan
      WHERE listing_Type = 'AARM'
        AND u_kbalikepartnumbers_id = 1000307
        AND ( EXTRACT( DAY FROM ( NOW() - dateEnded ) ) ) * 24 < 48
        AND COALESCE( price, 0 ) > ( SELECT AVG( COALESCE( price, 0 ) )* 0.50
                                     FROM ( SELECT *, cume_dist() OVER ( ORDER BY price DESC )
                                           FROM web_price_scan
                                           WHERE listing_Type='AARM'
                                             AND u_kbalikepartnumbers_id = 1000307
                                             AND ( EXTRACT( DAY FROM ( NOW() - dateEnded ) ) ) * 24 < 48
                                         ) g
                                    WHERE cume_dist < 0.50
                                  )
        AND COALESCE( price, 0 ) < ( SELECT AVG( COALESCE( price, 0 ) ) *2
                                     FROM( SELECT *, cume_dist() OVER ( ORDER BY price desc )
                                           FROM web_price_scan
                                           WHERE listing_Type='AARM'
                                             AND u_kbalikepartnumbers_id = 1000307
                                             AND ( EXTRACT( DAY FROM ( NOW() - dateEnded ) ) ) * 24 < 48
                                         ) d
                                     WHERE cume_dist < 0.50)
     )s
HAVING COUNT(*) > 5

IMHO COALESCEAVG値を変更するため、で使用しないでください。NULL未知のものを意味し、他には何もない。での使用とは異なりSUMます。この例では、で置き換えAVGSUMも、結果は歪んでいません。合計に0を追加しても害はありませんが、不明な値の0で平均を計算すると、実際の平均は得られません。

その場合、これらの不明な値を回避するためprice IS NOT NULLWHERE節を追加します。


1
@Andrew私はあなたのクエリを使って例を挙げようとしました。しかし、私は迷子になります。このクエリが機能するとは思えません。from web_price_scan...繰り返されているようです...
Luc M

不思議に思う人にとっては、と等しい場合に返されるという点NULLIF(v1, v2)COALESCE、ほぼ逆のことをします。NULLv1v2
2016年

24

(この回答は、質問に短くてより一般的な例を提供するために追加されました-元の質問にすべてのケース固有の詳細を含めることはありません)。


ここには2つの異なる「問題」があります。1つ目はテーブルまたはサブクエリに行がない場合、2つ目はクエリにNULL値がある場合です。

私がテストしたすべてのバージョンで、postgresとmysqlは平均化時にすべてのNULL値を無視し、平均化するものがない場合はNULLを返します。NULLは「不明」と見なされるため、これは一般的に意味があります。これを上書きしたい場合は、(Luc Mの提案に従って)結合を使用できます。

$ create table foo (bar int);
CREATE TABLE

$ select avg(bar) from foo;
 avg 
-----

(1 row)

$ select coalesce(avg(bar), 0) from foo;
 coalesce 
----------
        0
(1 row)

$ insert into foo values (3);
INSERT 0 1
$ insert into foo values (9);
INSERT 0 1
$ insert into foo values (NULL);
INSERT 0 1
$ select coalesce(avg(bar), 0) from foo;
      coalesce      
--------------------
 6.0000000000000000
(1 row)

もちろん、「from foo」は「from(...複雑なロジックはここに...)as foo」に置き換えることができます。

ここで、テーブルのNULL行を0としてカウントする必要がありますか?次に、合体をavg呼び出し内で使用する必要があります。

$ select coalesce(avg(coalesce(bar, 0)), 0) from foo;
      coalesce      
--------------------
 4.0000000000000000
(1 row)

2

これを実現する方法は2つ考えられます。

  • IFNULL():

    IFNULL()関数は、式がNULLの場合、指定された値を返します。式がNOT NULLの場合、この関数は式を返します。

構文:

IFNULL(expression, alt_value)

クエリを含むIFNULL()の例:

SELECT AVG( price )
FROM(
      SELECT *, cume_dist() OVER ( ORDER BY price DESC ) FROM web_price_scan
      WHERE listing_Type = 'AARM'
        AND u_kbalikepartnumbers_id = 1000307
        AND ( EXTRACT( DAY FROM ( NOW() - dateEnded ) ) ) * 24 < 48
        AND IFNULL( price, 0 ) > ( SELECT AVG( IFNULL( price, 0 ) )* 0.50
                                     FROM ( SELECT *, cume_dist() OVER ( ORDER BY price DESC )
                                           FROM web_price_scan
                                           WHERE listing_Type='AARM'
                                             AND u_kbalikepartnumbers_id = 1000307
                                             AND ( EXTRACT( DAY FROM ( NOW() - dateEnded ) ) ) * 24 < 48
                                         ) g
                                    WHERE cume_dist < 0.50
                                  )
        AND IFNULL( price, 0 ) < ( SELECT AVG( IFNULL( price, 0 ) ) *2
                                     FROM( SELECT *, cume_dist() OVER ( ORDER BY price desc )
                                           FROM web_price_scan
                                           WHERE listing_Type='AARM'
                                             AND u_kbalikepartnumbers_id = 1000307
                                             AND ( EXTRACT( DAY FROM ( NOW() - dateEnded ) ) ) * 24 < 48
                                         ) d
                                     WHERE cume_dist < 0.50)
     )s
HAVING COUNT(*) > 5
  • COALESCE()

    COALESCE()関数は、リスト内の最初のnull以外の値を返します。

構文:

COALESCE(val1, val2, ...., val_n)

クエリを使用したCOALESCE()の例:

SELECT AVG( price )
FROM(
      SELECT *, cume_dist() OVER ( ORDER BY price DESC ) FROM web_price_scan
      WHERE listing_Type = 'AARM'
        AND u_kbalikepartnumbers_id = 1000307
        AND ( EXTRACT( DAY FROM ( NOW() - dateEnded ) ) ) * 24 < 48
        AND COALESCE( price, 0 ) > ( SELECT AVG( COALESCE( price, 0 ) )* 0.50
                                     FROM ( SELECT *, cume_dist() OVER ( ORDER BY price DESC )
                                           FROM web_price_scan
                                           WHERE listing_Type='AARM'
                                             AND u_kbalikepartnumbers_id = 1000307
                                             AND ( EXTRACT( DAY FROM ( NOW() - dateEnded ) ) ) * 24 < 48
                                         ) g
                                    WHERE cume_dist < 0.50
                                  )
        AND COALESCE( price, 0 ) < ( SELECT AVG( COALESCE( price, 0 ) ) *2
                                     FROM( SELECT *, cume_dist() OVER ( ORDER BY price desc )
                                           FROM web_price_scan
                                           WHERE listing_Type='AARM'
                                             AND u_kbalikepartnumbers_id = 1000307
                                             AND ( EXTRACT( DAY FROM ( NOW() - dateEnded ) ) ) * 24 < 48
                                         ) d
                                     WHERE cume_dist < 0.50)
     )s
HAVING COUNT(*) > 5

1
IFNULL()はPostgresの関数ではありません。これは他のデータベースでも機能する可能性がありますが、問題は特にPostgresに関するものです。
Jon Wilson
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.