2012-06-13 21 views
55

Tengo una consulta que devuelve promedio (precio)PostgreSQL devolver 0 si el valor devuelto es nulo

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 

cómo hacerlo volver 0 si ningún valor está disponible?

+1

¿Estás seguro de que tu consulta está bien formada? –

+2

@LucM: No puede ser una consulta bien formada. (cláusula "having" sin una cláusula "group by".) –

+0

todo funciona bien, excepto que a veces, cuando no se cumplen las reglas, no devuelve nada. Además, ¿cómo puedo aumentar el promedio, no creo que sea posible? ¿Cuál es el objetivo? Múltiples selecciones 'from web_price_scan' son selecciones separadas; no estoy seguro de cuál es el problema aquí? – Andrew

Respuesta

116

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

Editar Here'san ejemplo de COALESCE con su consulta:

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 

mi humilde opinión COALESCE no debe ser el uso con AVG ya que modifica el valor. NULL significa desconocido y nada más. No es como usarlo en SUM. En este ejemplo, si reemplazamos AVG por SUM, el resultado no se distorsiona. Agregar 0 a una suma no hace daño a nadie, pero al calcular un promedio con 0 para los valores desconocidos, no se obtiene el promedio real.

En ese caso, agregaría price IS NOT NULL en la cláusula WHERE para evitar estos valores desconocidos.

+0

No pude hacerlo funcionar; ejemplo ayudaría – Andrew

+1

@Andrew. Estaba tratando de darle un ejemplo usando su consulta. Pero me pierdo Dudo que esta consulta funcione. 'from web_price_scan ...' parece repetido ... –

+0

Para aquellos que se preguntan, ['NULLIF (v1, v2)'] (https://www.postgresql.org/docs/current/static/functions-conditional.html) hace más o menos lo contrario de 'COALESCE' en que devuelve' NULL' si 'v1' es igual a' v2'. –

11

(esta respuesta se agregó para proporcionar ejemplos más cortos y genéricos a la pregunta, sin incluir todos los detalles específicos de cada caso en la pregunta original).


hay dos "problemas" distintas aquí, la primera es si una tabla o subconsulta tiene ninguna fila, el segundo es si hay valores NULL en la consulta.

Para todas las versiones que he probado, postgres y mysql ignorarán todos los valores NULL al promediar, y devolverán NULL si no hay nada que promedie. Esto generalmente tiene sentido, ya que NULL se debe considerar "desconocido". Si quieres anular esto, puedes usar coalesce (como lo sugirió 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) 

por supuesto, "de foo" puede sustituirse por "de (... cualquier lógica complicada aquí ...) como foo"

Ahora, se debe contar la fila NULL en la tabla como 0? Luego se debe combinar dentro de la llamada avg.

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