2012-06-13 12 views
55

私はAVG(価格を)返すクエリを持って0を返すPostgreSQLの

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

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

+2

@LucM:整形式のクエリはできません。 (「グループ化」節なしの「having」節) –

+0

すべてが正常に機能しますが、規則が満たされない場合は何も返されません。また、平均的にどのようにしたらいいですか、それは可能だとは思いません。 multiple from 'web_price_scanから'は別々のselectです。ここで何が問題なのかよくわからない? – Andrew

答えて

116

使用coalesce

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の編集 Here'san例:

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 

それが修飾するので私見COALESCEAVGで使用すべきではありません値。 NULLは未知のことを意味し、それ以外は何も意味しません。それはSUMでそれを使用するようではありません。この例では、AVGSUMに置き換えると、結果は歪まない。合計に0を加えても、未知の値に対して0で平均値を計算するだけで誰も傷つけることはありません。実際の平均値は得られません。

この場合、これらの未知の値を避けるために、節にprice IS NOT NULLを追加します。

+0

私はそれを動作させることができませんでした。例が助けてくれる – Andrew

+1

@Andrewあなたの質問を使って例を挙げようとしていました。しかし、私は失われます。この質問がうまくいくかどうかは疑問です。 'from web_price_scan ...'が繰り返されているようです... –

+0

疑問のある人には、['NULLIF(v1、v2)'](https://www.postgresql.org/docs/current/static/functions-conditional.html) 'v1'が' v2'ならば 'NULL'を返すという点で、' COALESCE'とはかなり反対です。 –

11

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


は、クエリ内のNULL値がある場合には、第2は、テーブルまたはサブクエリが行を持っていない場合、最初は、ここでは二つの異なる「問題」があります。

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

もちろん
$ 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) 

は、今

「FOOとして(ここで...複雑なロジック...)から」、テーブル内のNULL行がカウントされるべきで置き換えることができます0として?次に、coalesceをavgコールの内部で使用する必要があります。

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