2014-07-18 35 views
14

Próbuję następujące zapytanie.Jak przekonwertować PostgreSQL 9.4 typ jsonb unosić

SELECT (json_data->'position'->'lat') + 1.0 AS lat FROM updates LIMIT 5; 

(1,0 jest tylko tam, aby wymusić konwersję do pływaka mojego aktualnego zapytania są znacznie bardziej skomplikowane, zapytanie to jest tylko przypadek testowy dla problemu)

pojawia się błąd.

ERROR: operator does not exist: jsonb + numeric 

Jeśli dodać w wyraźnej rzucania:

SELECT (json_data->'position'->'lat')::float + 1.0 AS lat FROM updates LIMIT 5; 

błąd staje:

ERROR: operator does not exist: jsonb + double precesion 

Rozumiem, że większość wartości jsonb nie może być wrzucony do pływaków, ale w tym przypadku wiem, że łata są wszystkie numery JSON.

Czy istnieje funkcja, która rzuca wartości jsonb na wartości pływające (lub zwraca wartości NULL dla nieoznaczalnego)?

+0

Nie ma 'try_cast' funkcja domyślnie w PostgreSQL. Musisz napisać je sam. –

Odpowiedz

38

Istnieją dwie operacje, aby uzyskać wartość od JSON. Pierwszy: -> zwróci JSON. Drugi: ->> zwróci tekst.

Szczegóły: JSON Functions and Operators

Try

SELECT (json_data->'position'->>'lat')::float + 1.0 AS lat 
FROM updates 
LIMIT 5 
+0

prawdopodobnie nie chcesz zepsuć wartości, więc używaj :: float + 0.0 AS lat, zmiana 1 lat to bardzo duża różnica !! –

3

AFAIK nie ma json-> pływak odlewania w PostgreSQL, więc można spróbować wyraźne (json_data->'position'->'lat')::text::float cast

5

Per documentation, istnieją również funkcje

jsonb_populate_record() 
jsonb_populate_recordset() 

analogowe do swoich bliźniaków json (obecny od pg 9.3)

json_populate_record() 
json_populate_recordset() 

Potrzebujesz predefiniowanego typu wiersza. Użyj typu wiersza istniejącej tabeli lub zdefiniuj go za pomocą CREATE TYPE. Możesz też zastąpić tymczasową tabelą ad hoc:

CREATE TEMP TABLE x(lat float);

Może to być pojedyncza kolumna lub długa lista kolumn.

Tylko te kolumny są wypełnione, gdzie nazwadopasowuje klucza w obiekcie json. Wartość o wartości jest wymuszana na kolumnie typu i musi być zgodna lub zgłaszany jest wyjątek. Pozostałe klucze są ignorowane.

SELECT lat + 1 -- no need for 1.0, this is float already 
FROM updates u 
    , jsonb_populate_record(NULL::x, u.json_data->'position') 
LIMIT 5; 

Tutaj można skorzystać z implicit LATERAL JOIN.

Podobnie, użyj jsonb_populate_recordset(), aby rozłożyć tablice na wiele wierszy na pozycję.

Działa to w ten sam sposób w PostgreSQL 9.3 z json. Istnieje dodatkowa korzyść polegająca na tym, że odlewanie do/z text wewnętrznie nie jest konieczne dla danych numerycznych w jsonb.

0

Musisz rzucić wartość json do tekstu, a następnie float.

Spróbuj tego:

(json_data #>> '{field}')::float