2014-07-18 8 views
14

sto cercando la seguente query:.Come convertire PostgreSQL 9.4 di tipo jsonb di galleggiare

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

(Il 1,0 è solo lì per forzare la conversione di galleggiare mie query effettivi sono molto più complesse, questa query è solo un banco di prova per il problema)

ottengo l'errore:.

ERROR: operator does not exist: jsonb + numeric 

Se aggiungo in fusione di esplicito:

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

l'errore diventa:

ERROR: operator does not exist: jsonb + double precesion 

ho capito che la maggior parte dei valori jsonb non possono essere gettati nel galleggianti, ma in questo caso so che il lat sono tutti i numeri di JSON.

Esiste una funzione che converte i valori jsonb in float (o restituisce NULL per l'uncastable)?

+0

Non ci sono alcun 'try_cast' funzione di default in Postgres. Devi scriverli da solo. –

risposta

38

Ci sono due operazioni per ottenere il valore da JSON. Il primo -> restituirà JSON. Il secondo ->> restituirà il testo.

Dettagli: JSON Functions and Operators

provare

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

probabilmente non si vuole rovinare il valore in modo da usare: float + 0.0 AS lat, 1 lat change è una differenza molto grande !! –

3

Per quanto ne sappia non c'è json-> fusione in Postgres galleggiante, così si potrebbe provare un esplicito (json_data->'position'->'lat')::text::float gettato

5

Per documentation, ci sono anche le funzioni

jsonb_populate_record() 
jsonb_populate_recordset() 

analogico ai loro gemelli JSON (presenti dal pg 9.3)

json_populate_record() 
json_populate_recordset() 

È necessario un tipo di riga predefinito. Utilizzare il tipo di riga di una tabella esistente o definirne uno con CREATE TYPE. O sostituire con una tabella temporanea ad hoc:

CREATE TEMP TABLE x(lat float);

può essere una singola colonna o una lunga lista di colonne.

solo le colonne sono riempite, in cui il nome corrisponde a un chiave nell'oggetto json. Il valore è forzato alla colonna tipo e deve essere compatibile oppure viene sollevata un'eccezione. Altre chiavi sono ignorate.

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; 

Utilizzo di implicit LATERAL JOIN qui.

Analogamente, utilizzare jsonb_populate_recordset() per decomporre gli array in più righe per voce.

Questo funziona allo stesso modo in Postgres 9.3 con json. Vi è il vantaggio aggiunto che la trasmissione da/a text internamente non è necessaria per i dati numerici in jsonb.

0

È necessario eseguire il cast del valore json in testo e quindi in virgola mobile.

Prova questa:

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