2012-06-13 37 views
55

Tôi có một truy vấn mà trả trung bình (giá)PostgreSQL trở về 0 nếu giá trị trả về là null

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 

làm thế nào để làm cho nó trở về 0 nếu không có giá trị có sẵn?

+1

Bạn có chắc chắn rằng bạn đang truy vấn được định dạng đúng không? –

+2

@LucM: Nó không thể là một truy vấn đúng ngữ pháp. ("có" khoản mà không có một "nhóm theo" khoản.) –

+0

tất cả mọi thứ làm việc tốt, ngoại trừ đôi khi, khi các quy tắc không được đáp ứng, nó không trả lại bất cứ điều gì. Ngoài ra, làm thế nào tôi có thể gorup trung bình, tôi không nghĩ rằng nó là có thể || whats điểm? Nhiều lựa chọn 'từ web_price_scan' là các lựa chọn riêng biệt; không chắc vấn đề ở đây là gì? – Andrew

Trả lời

116

sử dụng 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. 

Sửa Here'san ví dụ về liên hiệp với truy vấn của bạn:

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 COALESCE không nên sử dụng với AVG vì nó đổi giá trị. NULL nghĩa là không biết và không có gì khác. Nó không giống như sử dụng nó trong SUM. Trong ví dụ này, nếu chúng tôi thay thế AVG theo SUM, kết quả sẽ không bị méo. Thêm 0 vào tổng không làm tổn thương bất cứ ai nhưng tính trung bình với 0 cho các giá trị không xác định, bạn không nhận được mức trung bình thực.

Trong trường hợp đó, tôi sẽ thêm price IS NOT NULL vào mệnh đề WHERE để tránh các giá trị không xác định này.

+0

Tôi không thể làm cho nó hoạt động; ví dụ sẽ giúp – Andrew

+1

@Andrew Tôi đã cố gắng cung cấp cho bạn một ví dụ sử dụng truy vấn của bạn. Nhưng tôi bị lạc. Tôi nghi ngờ rằng truy vấn này hoạt động. 'từ web_price_scan ...' có vẻ lặp đi lặp lại ... –

+0

Đối với những người tự hỏi, ['NULLIF (v1, v2)'] (https://www.postgresql.org/docs/current/static/functions-conditional.html) thực hiện khá nhiều điều ngược lại với 'COALESCE' ở chỗ nó trả về' NULL' nếu 'v1' bằng' v2'. –

11

(câu trả lời này được thêm vào để cung cấp các ví dụ ngắn hơn và chung chung hơn cho câu hỏi - mà không bao gồm tất cả các chi tiết cụ thể về trường hợp trong câu hỏi gốc).


Có hai "vấn đề" khác biệt ở đây, là người đầu tiên là nếu một bảng hoặc subquery không có hàng, thứ hai là nếu có giá trị NULL trong truy vấn.

Đối với tất cả các phiên bản tôi đã thử nghiệm, postgres và mysql sẽ bỏ qua tất cả các giá trị NULL khi trung bình, và nó sẽ trả về NULL nếu không có gì để trung bình hơn. Điều này thường có ý nghĩa, vì NULL được coi là "không xác định". Nếu bạn muốn ghi đè điều này, bạn có thể sử dụng kết hợp (như đề xuất bởi 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) 

tất nhiên, "từ foo" có thể được thay thế bằng "từ (... bất kỳ logic phức tạp ở đây ...) như foo"

Bây giờ, nên hàng NULL trong bảng được tính là 0? Sau đó, coalesce phải được sử dụng bên trong cuộc gọi avg.

$ select coalesce(avg(coalesce(bar, 0)), 0) from foo; 
     coalesce  
-------------------- 
4.0000000000000000 
(1 row) 
Các vấn đề liên quan