postgresql trả về 0 nếu giá trị trả về là null


99

Tôi có một truy vấn trả về trung bình (giá)

  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ị nào?


1
Bạn có chắc rằng truy vấn của bạn đã được định dạng tốt?
Luc M

2
@LucM: Nó không thể là một truy vấn được định dạng tốt. (Mệnh đề "có" mà không có mệnh đề "nhóm theo".)
Mike Sherrill 'Cat Nhớ lại'

mọi thứ hoạt động 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 theo mức trung bình, tôi không nghĩ là có thể || vấn đề là gì? Nhiều lựa chọn from web_price_scanlà các lựa chọn riêng biệt; không chắc chắn những gì vấn đề ở đây?
Andrew

Bạn có thể sử dụng havingmệnh đề không có group by(mặc định cho một nhóm duy nhất). Nó hoạt động như một wheremệnh đề về kết quả tổng hợp. Trong trường hợp này, các hàng chỉ được trả về nếu hơn 5 hàng được trả về bởi truy vấn con cấp 1.
bruceskyaus

Câu trả lời:


177

sử dụng liên kết

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.

Biên tập

Đây là một ví dụ về COALESCEtruy 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

COALESCEKhông nên sử dụng IMHO với AVGvì nó sửa đổi giá trị. NULLnghĩa là chưa 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 ta thay thế AVGbằng SUM, kết quả không bị bóp méo. Việc thêm 0 vào một tổng không làm hại ai nhưng tính trung bình với 0 cho các giá trị chưa biết, bạn sẽ không nhận được giá trị trung bình thực.

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


1
@Andrew Tôi đang cố gắng cung cấp cho bạn một ví dụ bằng cách 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. from web_price_scan...dường như lặp đi lặp lại ...
Luc M

Đối với những người thắc mắc, NULLIF(v1, v2)điều ngược lại hoàn toàn với COALESCEnó trả về NULLnếu v1bằng v2.
sm

24

(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 về trường hợp cụ thể trong câu hỏi ban đầu).


Có hai "vấn đề" khác biệt ở đây, thứ nhất là nếu bảng hoặc truy vấn con 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 tính giá trị trung bình và nó sẽ trả về NULL nếu không có giá trị trung bình nào vượt qua. Đ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 (theo gợi ý của 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, "from foo" có thể được thay thế bằng "from (... bất kỳ logic phức tạp nào ở đây ...) as foo"

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

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

2

Tôi có thể nghĩ ra 2 cách để đạt được điều này:

  • IFNULL ():

    Hàm IFNULL () trả về một giá trị được chỉ định nếu biểu thức là NULL. Nếu biểu thức KHÔNG ĐỦ, hàm này trả về biểu thức.

Cú pháp:

IFNULL(expression, alt_value)

Ví dụ về IFNULL () 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 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 ()

    Hàm COALESCE () trả về giá trị không rỗng đầu tiên trong danh sách.

Cú pháp:

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

Ví dụ về COALESCE () 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

1
IFNULL () không phải là một hàm trong Postgres. Điều này có thể hoạt động trong các cơ sở dữ liệu khác nhưng câu hỏi đặc biệt là về Postgres.
Jon Wilson
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.