How to compare double precision arrays - postgresql

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[]

Related

postgresql malformed array literal in create aggregate initcond

Running postgres 11.3. Here's the sql code
create type _stats_agg_accum_type AS (
cnt bigint,
min double precision,
max double precision,
m1 double precision,
m2 double precision,
m3 double precision,
m4 double precision,
q double precision[],
n double precision[],
np double precision[],
dn double precision[]
);
create aggregate stats_agg(double precision) (
sfunc = _stats_agg_accumulator,
stype = _stats_agg_accum_type,
finalfunc = _stats_agg_finalizer,
combinefunc = _stats_agg_combiner,
parallel = safe,
initcond = '(0,,, 0, 0, 0, 0, {}, {1,2,3,4,5}, {1,2,3,4,5}, {0,0.25,0.5,0.75,1})'
);
Which gives me
ERROR: malformed array literal: "{1"
DETAIL: Unexpected end of input.
SQL state: 22P02
The empty array literal works ok. I've also tried a one element literal {1} which works fine. Whenever I have 2 or more elements it gives me this error.
As a work around I could pass in empty arrays and initialize them on the first pass, but that's ugly.
You need quotes around your arrays, and that's because the array is in a text version of a row.
Easy to test by taking your input as a row and see how postgres formats it (single quotes needed around arrays here because {} is an array in text):
SELECT ROW(0,NULL,NULL, 0, 0, 0, 0, '{}', '{1,2,3,4,5}', '{1,2,3,4,5}', '{0,0.25,0.5,0.75,1}')
Returns:
(0,,,0,0,0,0,{},"{1,2,3,4,5}","{1,2,3,4,5}","{0,0.25,0.5,0.75,1}")
Therefore you need to do:
...
initcond = '(0,,,0,0,0,0,{},"{1,2,3,4,5}","{1,2,3,4,5}","{0,0.25,0.5,0.75,1}")'
Why quotes are not required on an array which is empty or has only one value:
Multiple values in an array are comma-delimited, and fields within a row are also comma-delimited. If you supply a row as '(0,{1,2})', PG will interpret this as three fields: 0, {1, 2}. Naturally in that case you'll get an error about a malformed array. Putting a field in quotes means everything within those quotes is one field. Therefore '(0,"{1,2}")' will be interpreted correctly as 0, {1,2}. If the array is empty or contains only one value, there will be no comma, so there is no problem parsing that field correctly.

PostgreSQL insert from SQL SELECT statement fails because of expression type text

I'm running into a simple error on PostgreSQL inserting data into a new table. I'd like to use a simple query because this table is only going to store averages across different dimensions. I want my avg column to be double precision. My insert statement is
insert into benchmark_table
(select avg(s.percentage_value) as avg, s.metric_name, s.category
from some_table s group by s.category, s.metric_name);
This command fails with the following error:
ERROR: column "avg" is of type double precision but expression is of
type text LINE 2: ...(s.percentage_value) as double precision) as avg,
s.metric_n...
^ HINT: You will need to rewrite or cast the expression.
So I try casting my avg column to double precision:
INSERT into benchmark_table
(SELECT cast(avg(s.percentage_value) as double precision) as avg, s.metric_name, s.category
FROM some_table s group by s.category, s.metric_name);
I've also attempted
insert into benchmark_table
(Select avg(s.percentage_value)::double precision as avg, s.metric_name, s.category
from summary_view_output s group by s.category, s.metric_name);
However, I get the same error about avg being text. I understand that what's being returned from my query is a result set that is by default text, but I'm not seeing any way to convert this into another datatype for my outer INSERT statement to use.
Try to change the ::double precision to ::float and see if that works. Also I noticed you aren't including the field names in the Insert clause. Maybe the ordinal position of the fields of the benchmark_table is not the same as in the select statement.
try to use.
insert into benchmark_table( avg, metric_name, category)

UNION ALL, cast NULL as double precision, Postgres

In postgres, I'm getting an error when I try to union two tables where one table has a column (Amount) containing double precision data type, and the other table does not have a matching column and I'd like the records from that table to just have NULL in the Amount field.
Error:
"union types text and double precision cannot be matched postgres"
Pseudo-code:
SELECT * FROM (
SELECT
t1.Amount AS 'amount',
NULL::DATE AS 'date'
FROM Table1 AS t1
UNION ALL
SELECT
/* next line is the issue */
NULL AS 'amount',
t2.Date AS 'date'
FROM Table2 AS t2
) AS FOO
I feel fairly certain this solution is a simple casting problem but could not find anything from searching. How do I do the equivalent of NULL::DOUBLE in postgres?
EDIT::POSTERITY
The accepted answer from #klin and #a_horse_with_no_name's comment that points to a "historical" postgres cast expression :: where the syntax is equivalent:
CAST ( expression AS type )
expression::type
And, here is a list of the postgres data types.
In Postgres the type double precision is also known as float8 or simply float. Use one of them.
select null::double precision, null::float;

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

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.

How can I convert the division of two integer values to a decimal using T-SQL against a iSeries AS/400 Database?

Assuming the following query:
SELECT
ID,
COUNT(1) AS NumRecords,
SUM(Quantity) AS TotalQty
SUM(Quantity)/COUNT(1) AS Avg
FROM SOME_TABLE
GROUP BY ID
Right now it returns:
ID NumRecords TotalQty Avg
1 15 6 2
I want it to return a decimal value with a Scale of 2 for Avg (i.e. "2.5").
I've tried to CAST the calcluation as a DECIMAL, NUMERIC, FLOAT, and VARCHAR, but it always returns an INTEGER.
You need to cast the inputs to the calculation not the result. Also any reason you aren't using the AVG function?
AVG(CAST(Quantity as decimal(10,2)))
An alternative solution is via implicit Casting. I found this to be much cleaner SQL as well. The precision will be determined by the number of trailing zeros used when multiplying by 1.
AVG(Quantity * 1.00) //x.xx
AVG(Quantity * 1.0000) //x.xxxx