Is there a sane way of storing int, float and boolean values in the same column in postgres?
If have something like that:
rid | time | value |
---|---|---|
2d9c5bdc-dfc5-4ce5-888f-59d06b5065d0 | 2021-01-01 00:00:10.000000 00:00 | true |
039264ad-af42-43a0-806b-294c878827fe | 2020-01-03 10:00:00.000000 00:00 | 2 |
b3b1f808-d3c3-4b6a-8fe6-c9f5af61d517 | 2021-01-01 00:00:10.000000 00:00 | 43.2 |
Currently I'm using jsonb to store it, the problem however now is, that I can't filter in the table with for instance the greater operator.
The query SELECT * FROM points WHERE value > 0;
gives back the error: ERROR: operator does not exist: jsonb > integer: No operator matches the given name and argument types. You might need to add explicit type casts.
For me it's okay to handle boolean as 1 or 0 in case of true
or false
. Is there any possibility to achieve that with jsonb or is there maybe another super type which lets me use a column which is able to use all three types?
Performance is not so much of a concern here, as I'm going to have very little records inside of that table, max 5k I guess.
Thanks in advance.
CodePudding user response:
If you were just storing integers and floats, normally you'd use a float
or numeric
column.
But there's that pesky true
.
You could cast the JSON...
select *
from test
where value::float > 1;
...but there's that pesky true
.
You have to convert the boolean to a number to make it work.
select *
from test
where
(case when value = 'true' then 1.0 when value = 'false' then 0.0 else value::float end) >= 1;
Or ignore it.
This having to work around the type system suggests that value
is actually two or even three different fields crammed into one. Consider separating them into multiple columns.
CodePudding user response:
You should skip the rows where value
is not number
and cast the value to numeric
, e.g.:
with points(id, value) as (
values
(1, 'true'::jsonb),
(2, '2'),
(3, '43.2')
)
select *
from points
where jsonb_typeof(value) = 'number'
and value::text::numeric > 0;
id | value
---- -------
2 | 2
3 | 43.2
(2 rows)