2013-09-23 11 views
22

Mam tabelę Postgres z kolumną ciągów zawierających wartości numeryczne. Muszę przekonwertować te łańcuchy na liczby dla matematyki, ale potrzebuję zarówno wartości NULL, jak i pustych ciągów, które będą interpretowane jako 0.Rzucić ciąg na numer, interpretując pusty lub pusty łańcuch jako 0

mogę convert empty strings into null values:

# select nullif('',''); 
nullif 
-------- 

(1 row) 

i mogę convert null values into a 0:

# select coalesce(NULL,0); 
coalesce 
---------- 
     0 
(1 row) 

i mogę convert strings into numbers:

# select cast('3' as float); 
float8 
-------- 
     3 
(1 row) 

Ale gdy próbuję połączyć te techniki, otrzymuję błędy:

# select cast(nullif(coalesce('',0), '') as float); 
ERROR: invalid input syntax for integer: "" 
LINE 1: select cast(nullif(coalesce('',0), '') as float); 

# select coalesce(nullif('3',''),4) as hi; 
ERROR: COALESCE types text and integer cannot be matched 
LINE 1: select coalesce(nullif('3',''),4) as hi; 

Co robię źle?

+3

marginesie - jest lepiej w większości przypadków użyj 'numeric' zamiast' float'. Użyj 'float' tylko wtedy, gdy wiesz, że naprawdę potrzebujesz' float'. –

Odpowiedz

22

Rodzaje wartości muszą być spójne; koalescencja pustego łańcucha do 0 oznacza, że ​​nie można go następnie porównać do null w nullif. Więc albo tych prac:

# create table tests (orig varchar); 
CREATE TABLE 

# insert into tests (orig) values ('1'), (''), (NULL), ('0'); 
INSERT 0 4 


# select orig, cast(coalesce(nullif(orig,''),'0') as float) as result from tests; 
orig | result 
------+-------- 
    1 |  1 
     |  0 
     |  0 
    0 |  0 
(4 rows) 


# select orig, coalesce(cast(nullif(orig,'') as float),0) as result from tests; 
orig | result 
------+-------- 
1 |  1 
     |  0 
     |  0 
0 |  0 
(4 rows) 
6

Można też użyć

cast(
    case 
     when coalesce(orig, '') = '' then '0' 
     else orig 
    end 
    as float 
) 

Można także rozpakować że nieco skoro jesteś rozpocząć dość rozwlekły i tak:

cast(
    case 
     when orig is null then '0' 
     when orig = '' then '0' 
     else orig 
    end 
    as float 
) 

czy mógłbyś wstaw obsadę do CASE:

case 
    when coalesce(orig, '') = '' then 0.0 
    else cast(orig as float) 
end 

CASE sprawia, że ​​łatwiej jest uwzględnić inne specjalne warunki, to również wydaje się wyraźniejszym wyrazem logicznego IMO. OTOH, osobisty gust i tak dalej.

3

Właściwie można rzutować NULL na int, po prostu nie można rzucić pustego ciągu na int. Zakładając, że chcesz NULL w nowej kolumnie jeśli dane1 zawiera pusty ciąg lub NULL, można zrobić coś takiego:

UPDATE table SET data2 = cast(nullif(data1, '') AS int); 

lub

UPDATE table SET data2 = nullif(data1, '')::int; 

Reference

+0

Od drugiego zdania: _ "[...] Potrzebuję zarówno wartości NULL, jak i pustych ciągów do interpretacji jako 0." _ – Phrogz