Zwróć 0, jeśli pole jest puste w MySQL

160

Czy w MySQL istnieje sposób na ustawienie zerowych pól „total”, jeśli mają wartość NULL?

Oto co mam:

SELECT uo.order_id, uo.order_total, uo.order_status,
            (SELECT SUM(uop.price * uop.qty) 
             FROM uc_order_products uop 
             WHERE uo.order_id = uop.order_id
            ) AS products_subtotal,
            (SELECT SUM(upr.amount) 
             FROM uc_payment_receipts upr 
             WHERE uo.order_id = upr.order_id
            ) AS payment_received,
            (SELECT SUM(uoli.amount) 
             FROM uc_order_line_items uoli 
             WHERE uo.order_id = uoli.order_id
            ) AS line_item_subtotal
            FROM uc_orders uo
            WHERE uo.order_status NOT IN ("future", "canceled")
            AND uo.uid = 4172;

Dane są w porządku, z wyjątkiem pól NULL 0.

Jak mogę zwrócić 0 dla NULL w MySQL?

Kevin
źródło

Odpowiedzi:

326

Użyj IFNULL :

IFNULL(expr1, 0)

Z dokumentacji:

Jeśli wyrażenie1 nie jest równe NULL, funkcja IFNULL () zwraca wyrażenie1; w przeciwnym razie zwraca wyr2. IFNULL () zwraca wartość liczbową lub łańcuchową, w zależności od kontekstu, w którym jest używana.

Mark Byers
źródło
Czy byłoby to IFNULL ((SELECT SUM (uop.price * uop.qty) FROM uc_order_products uop WHERE uo.order_id = uop.order_id) AS products_subtotal, 0)?
Kevin,
2
@Kevin: Nie - alias jest na końcu.
Mark Byers
2
@MarkByers Czy możesz pokazać, dlaczego przykład Kevina w komentarzu jest błędny i jaki powinien być?
Michael
Dziękuję bardzo !! Właśnie tego szukałem
brunobliss
@MarkByers IFNOtNULL (wyr1, 1) czy jest coś takiego
Noni
25

Możesz użyć coalesce(column_name,0)zamiast po prostu column_name. coalesceZwraca pierwszą wartość niezerowe na liście.

Powinienem wspomnieć, że takie funkcje dla wierszy są zwykle problematyczne dla skalowalności. Jeśli uważasz, że Twoja baza danych może dostać się pokaźnych rozmiarów, często lepiej jest użyć dodatkowych kolumn i wyzwala przenieść koszt od selectdo insert/update.

To amortyzuje koszt przy założeniu, że baza danych jest czytana częściej niż zapisywana (a większość z nich tak).

paxdiablo
źródło
Dzieje się to raz w tygodniu, aby obciążyć wszystkich klientów. Dane są zapisywane przez cały tydzień, a następnie o określonej godzinie są obliczane i rozliczane. Pomyśl o tym jak o usłudze subskrypcji. Możesz wprowadzać zmiany w trakcie trwania okresu rozliczeniowego, a opłata za Twoją działalność będzie naliczana w odpowiednich odstępach czasu.
Kevin
Dodam, że w tej sytuacji wolałbym koalesce, ponieważ to ta sama składnia dla MS i My SQLs, podczas gdy MS SQL to iSnull, a MySQL to iFnull, jeśli to dla kogoś ważne. (MySQLs ISNULL to inna funkcja niż MS SQL's ISNULL)
Craig Jacobs
11

Żadna z powyższych odpowiedzi nie była dla mnie kompletna. Jeśli twoje pole ma nazwę field, więc selektor powinien być następujący:

IFNULL(`field`,0) AS field

Na przykład w zapytaniu SELECT:

SELECT IFNULL(`field`,0) AS field, `otherfield` FROM `mytable`

Mam nadzieję, że to pomoże komuś nie tracić czasu.

Gianpaolo Papa
źródło
5

Możesz spróbować czegoś takiego

IFNULL(NULLIF(X, '' ), 0)

Zakłada się, że atrybut X jest pusty, jeśli jest pustym ciągiem, więc po tym można zadeklarować jako zero zamiast ostatniej wartości. W innym przypadku zachowałaby swoją pierwotną wartość.

W każdym razie, żeby dać inny sposób na zrobienie tego.

Ackuser
źródło
To zadziałało dla mnie świetnie w środku SELECT w porównaniu z normalnym IFNULL (var, 0)
ajankuv
5

Tak, funkcja IFNULL będzie działać, aby osiągnąć pożądany rezultat.

SELECT uo.order_id, uo.order_total, uo.order_status,
        (SELECT IFNULL(SUM(uop.price * uop.qty),0) 
         FROM uc_order_products uop 
         WHERE uo.order_id = uop.order_id
        ) AS products_subtotal,
        (SELECT IFNULL(SUM(upr.amount),0) 
         FROM uc_payment_receipts upr 
         WHERE uo.order_id = upr.order_id
        ) AS payment_received,
        (SELECT IFNULL(SUM(uoli.amount),0) 
         FROM uc_order_line_items uoli 
         WHERE uo.order_id = uoli.order_id
        ) AS line_item_subtotal
        FROM uc_orders uo
        WHERE uo.order_status NOT IN ("future", "canceled")
        AND uo.uid = 4172;
Krishna_K_Systematix
źródło