postgresql mengembalikan 0 jika nilai yang dikembalikan nol

102

Saya memiliki kueri yang mengembalikan rata-rata (harga)

  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

bagaimana membuatnya kembali 0 jika tidak ada nilai yang tersedia?

Andrew
sumber
1
Apakah Anda yakin bahwa kueri Anda berformat baik?
Luc M
2
@ LucM: Ini tidak bisa menjadi kueri yang dibentuk dengan baik. ("memiliki" klausa tanpa klausa "kelompok menurut".)
Mike Sherrill 'Cat Recall'
semuanya bekerja dengan baik, kecuali terkadang, ketika aturan tidak dipenuhi, tidak akan mengembalikan apapun. Selain itu, bagaimana saya bisa mendapatkan rata-rata gorup, menurut saya itu tidak mungkin || apa gunanya? Beberapa pilihan from web_price_scanadalah pilihan terpisah; tidak yakin apa masalahnya di sini?
Andrew
Tidak masalah menggunakan havingklausa tanpa group by(yang defaultnya ke satu grup). Ini bertindak sebagai whereklausul pada hasil agregat. Dalam kasus ini, baris hanya dikembalikan jika lebih dari 5 baris dikembalikan oleh subkueri tingkat 1.
bruceskyaus

Jawaban:

180

gunakan 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.

Edit

Berikut adalah contoh COALESCEdengan kueri Anda:

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 COALESCEtidak boleh digunakan dengan AVGkarena mengubah nilainya. NULLberarti tidak diketahui dan tidak ada yang lain. Ini tidak seperti menggunakannya dalam SUM. Dalam contoh ini, jika kita mengganti AVGdengan SUM, hasilnya tidak terdistorsi. Menambahkan 0 ke jumlah tidak merugikan siapa pun, tetapi menghitung rata-rata dengan 0 untuk nilai yang tidak diketahui, Anda tidak akan mendapatkan rata-rata sebenarnya.

Dalam hal ini, saya akan menambahkan price IS NOT NULLdi WHEREklausul untuk menghindari nilai-nilai yang tidak diketahui tersebut.

Luc M
sumber
1
@Andrew Saya mencoba memberi Anda contoh menggunakan kueri Anda. Tapi saya tersesat. Saya ragu kueri ini berhasil. from web_price_scan...tampaknya diulang ...
Luc M
Bagi mereka yang bertanya-tanya, NULLIF(v1, v2)apakah kebalikan dari COALESCEitu mengembalikan NULLjika v1sama v2.
sm
24

(jawaban ini ditambahkan untuk memberikan contoh yang lebih singkat dan lebih umum untuk pertanyaan - tanpa menyertakan semua detail khusus kasus di pertanyaan asli).


Ada dua "masalah" yang berbeda di sini, yang pertama adalah jika tabel atau subkueri tidak memiliki baris, yang kedua adalah jika ada nilai NULL dalam kueri.

Untuk semua versi yang saya uji, postgres dan mysql akan mengabaikan semua nilai NULL saat rata-rata, dan akan mengembalikan NULL jika tidak ada yang rata-rata di atas. Ini umumnya masuk akal, karena NULL dianggap "tidak diketahui". Jika Anda ingin menimpanya, Anda dapat menggunakan penggabungan (seperti yang disarankan oleh 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)

tentu saja, "dari foo" dapat diganti dengan "dari (... logika rumit apa pun di sini ...) sebagai foo"

Sekarang, haruskah baris NULL dalam tabel dihitung sebagai 0? Kemudian penggabungan harus digunakan di dalam panggilan rata-rata.

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

Saya dapat memikirkan 2 cara untuk mencapai ini:

  • IFNULL ():

    Fungsi IFNULL () mengembalikan nilai yang ditentukan jika ekspresi NULL. Jika ekspresi NOT NULL, fungsi ini mengembalikan ekspresi.

Sintaksis:

IFNULL(expression, alt_value)

Contoh IFNULL () dengan kueri Anda:

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
  • BERSATU()

    Fungsi COALESCE () mengembalikan nilai bukan nol pertama dalam daftar.

Sintaksis:

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

Contoh COALESCE () dengan kueri Anda:

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
Joish
sumber
1
IFNULL () bukan fungsi di Postgres. Ini mungkin berfungsi di database lain tetapi pertanyaannya secara khusus tentang Postgres.
Jon Wilson