Postgres convert from bytea which contains float (IEEE 754) to real (float4) - postgresql

The following SQL SELECT query returns an integer:
SELECT (((get_byte(dalsk.data, 0)::bit(8)) ||
(get_byte(dalsk.data, 1)::bit(8)) ||
(get_byte(dalsk.data, 2)::bit(8)) ||
get_byte(dalsk.data, 3)::bit(8)) :: bit(32)) :: integer --AS rezult_float
FROM (SELECT substring(data from 2 for 5) AS data FROM raw_data WHERE
raw_data_id = 33)
AS dalsk;
Whenever I try to cast the result from integer to real, I get the following error:
Cannot cast type bit to real.
Is there a way to convert the value to float?

The IEEE754 doesn't cover endianess so that's not enough info to convert the binary to float. If you want to convert it you will have to create a function or a cast operator.

Related

How to covert substring to integer?

I have varchar data then i want to convert it to integer so i can using the number to order my data this is my varchar
No.SKF.4-04/2021/CBO-ODSP
No.SKF.5-04/2021/CBO-ODSP
No.SKF.6-04/2021/CBO-ODSP
`
i want to take the number so i can select order the data
SELECT varchar from account_information order by CAST(substring(left("NO_SURAT", "length"("NO_SURAT")-17),8)as integer)
but it show some error
SELECT CAST(substring(left("NO_SURAT", "length"("NO_SURAT")-17),8)as integer) from account_information
ERROR: invalid input syntax for type integer: ""
how do i covert substring result to int?
Avoiding an expensive regular expression, you could use:
SELECT CAST(
substr(
'No.SKF.5-04/2021/CBO-ODSP',
8,
position('-' IN 'No.SKF.5-04/2021/CBO-ODSP') - 8
) AS integer
);
substr
════════
5
(1 row)

Postgres jsonb : cast array element to integer

Using Postgres 11.2.9 (ubuntu),
In my database, I have a jsonb field containing values that look like this :
[1618171589133, 1618171589245, 1618171589689]
I'd like to retrieve rows where the first element is lower than a specific value. I've tried this :
SELECT * FROM user.times WHERE time ->> 0 < 1618171589133
but I get the following error : ERROR: operator does not exist: text = bigint
Should I somehow cast the time value to numeric value ? I've tried time ->> 0::numeric but I actually don't know what to do.
The ->> operator returns the element at given position as text, which you can then convert to integer (or as it seems in this case, bigint), as you would normally do in postgres, using the :: as suffix.
SELECT * FROM user.times WHERE ((time ->> 0)::bigint) < 1618171589133

How to compare double precision arrays

Simply want to compare double precision column values that return results that are also double precision.
Using PostgreSQL 9.6 I haven't found a way to compare arrays of float or numeric data types without converting them to integers.
select * from
(
select
t1."SubdSec-in-DCA_id",
t1."float_range" as left_side,
t2."float_range" as right_side,
t1."float_range"::numeric[] - t2."float_range"::numeric[] as results
from "TEST" t1
cross join lateral (select "float_range" from "TEST") t2
) t3
order by "SubdSec-in-DCA_id",left_side, right_side
t1."float_range"::int[] & t2."float_range"::int[] as results,
works: but return values as integers
result: "T_S07414_DCA4117","{197.598,205.382}","{146.5,146.9}","{198,205}"
t1."float_range"::float[] & t2."float_range"::float[] as results,
fails: ERROR: operator does not exist: double precision[] & double precision[]
t1."float_range"::numeric[] & t2."float_range"::numeric[] as results
fails: ERROR: operator does not exist: numeric[] & numeric[]

Convert a bytea into a binary string

I need to decode a base64 string and take a chunk of binary.
Is there a SQL function in Postgres to simply convert a bytea into a binary string representation?
(Like "00010001010101010".)
If your Postgres installation runs with the default setting bytea_output = 'hex', there is a very simple hack:
SELECT right(bytea_col::text, -1)::varbit;
Example:
SELECT right((bytea '\xDEADBEEF')::text, -1)::varbit;
Result:
'11011110101011011011111011101111'
right(text, -1) is just the cheapest way to remove the leading backslash from the text representation.
varbit (standard SQL name bit varying) is for bit strings of arbitrary length. Cast the result to text or varchar if you like.
Related, with explanation:
Convert hex in text representation to decimal number
demo:db<>fiddle
You could put the following code into a function:
WITH byte AS ( -- 1
SELECT E'\\xDEADBEEF'::bytea as value
)
SELECT
string_agg( -- 5
get_byte(value, gs)::bit(8)::text -- 4
, ''
)
FROM
byte,
generate_series( -- 3
0,
length(value) - 1 -- 2
) gs
I demonstrated the development of the query within the fiddle.
The WITH clause encapsulates the bytea value for double usage in further code
length() calculates the binary length of the bytea value
generate_series() creates a list from 0 to length - 1 (0 - 3 in my example)
get_byte() takes the bytea value a second time and gives out the byte at position gs (the previous calculated values 0-3). This gives an integer representation of the the byte. After that the cast to bit(8) type converts the result of this function to its binary representation (1 byte = 8 bit)
string_agg() finally aggregates all for binary strings into one. (taking its text representations instead of bit type, with no delimiters)
A function could look like this:
CREATE OR REPLACE FUNCTION to_bit(value bytea) RETURNS SETOF text AS
$$
BEGIN
RETURN QUERY
SELECT
string_agg(get_byte(value, gs)::bit(8)::text, '')
FROM
generate_series(0, length(value) - 1) gs;
END;
$$ LANGUAGE plpgsql;
After that you could call it:
SELECT to_bit(E'\\xDEADBEEF'::bytea)
You could try it using get_bit() instead of get_byte(). This safes you the ::bit(8) cast but of course you need to multiply the length with factor 8 indeed.
The resulting bit string has another bit order but maybe it fits your use case better:
WITH byte AS (
SELECT E'\\xDEADBEEF'::bytea as value
)
SELECT
string_agg(get_bit(value, gs)::text, '')
FROM
byte,
generate_series(0, length(value) * 8 - 1) gs
demo:db<>fiddle

syntax used to type cast date(data type_ to integer in postgresql

I want convert Date data type to Integer, i have tried to type cast the date(data type) to integer by using ::INT, its not working.
I have got the following error
ERROR: column "date" is of type integer but expression is of type
date HINT: You will need to rewrite or cast the expression.
What you can do is:
replace(your_date::varchar, '/', '')::integer
Full example:
select replace(now()::date::varchar, '-', '')::integer
Use the TO_CHAR function with FM prefix and then cast it to Integer.
select to_char(date_column,'FMddFMmmYYYY')::INT as dateint FROM t
Demo