I want to calculate the average number from a column in PostgreSQL
SELECT AVG(col_name)
From TableName
It gives me this error:
ERROR: function avg (character varying) does not exist
LINE 1: SELECT AVG(col_name)
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Store numbers in a numeric field, an integer, decimal or whatever. But not in a text/varchar field.
Check the manual for all numeric data types.
Nasty workaound: CAST some records to a numeric value and keep others as text. Example:
/*
create temp table foo AS
SELECT x FROM (VALUES('x'),('1'),('2')) sub(x);
*/
WITH cte AS (
SELECT
CASE
WHEN x ~ '[0-9]' THEN CAST(x AS decimal) -- cast to numeric field
END AS num,
CASE
WHEN x ~ '[a-zA-Z]' THEN x
END AS a
FROM foo
)
SELECT AVG(num), COUNT(a) FROM cte;
Related
My query in postgresql 10, raises an error when it uses within GROUP clause
ERROR: function string_agg(character varying, unknown, integer) does
not exist
I have tables at and atrelation. at has unique id and description while atrelation stores multiple transaction with code of related at and transaction line id. for example
product row with id 6 has a column name tag has value service5% and contco4.5%
product row with id 5 has tag value service5%
I need to show 2-rows i.e row 6 and 5.
row 5 show the column tag value 'service5% and contco4.5% '
row 6 show the column tag value 'service5%'
select atrelation.id,
string_agg(at.description, ' and ' ) within GROUP (ORDER BY atrelation.id ) as tag1
from at, atrelation
where atrelation.id = atrelation.atid
group by atrelation.id
order by atrelation.id desc;
above query raise following error,
ERROR: function string_agg(character varying, unknown, integer) does not exist
LINE 1: select atrelation.purchase_order_line_id as id, string_agg(a...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
********** Error **********
ERROR: function string_agg(character varying, unknown, integer) does not exist
SQL state: 42883
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Character: 49
You need to put the ORDER BY into the function call and remove the WITHIN GROUP part:
string_agg(at.description, ' and ' ORDER BY atrelation.id) as tag1
I'm facing a strange behaviour when using a function to cast to composite type in Postgres 9.6.
I have declared a composite type "vector" as x,y,z - each of double precision as well as a cast as follows:
create type vector as(
x double precision,
y double precision,
z double precision
);
create cast (text as vector)
with function vector_from_text(text) as implicit;
Function vector_from_text looks like this:
create or replace function vector_from_text(text, out result vector) strict immutable language plpgsql as $$
declare
d double precision[];
begin
result := null;
if ($1 is null) then
return;
end if;
begin
with c1 as (
select $1::jsonb src
)
select row((src->>'x')::double precision, (src->>'y')::double precision, (src->>'z')::double precision)::vector
**into result** -- see below
from c1;
exception
when others then
d := translate($1, '()', '{}')::double precision[];
result := row(d[1], d[2], d[3])::vector;
end;
end$$
;
The function returns null on null, or a vector type for both input formats either a json-string like '{"x":0, "y":0, "z":0}' or a constructor expression like '(0,0,0)'.
The Problem:
For json-like inputs the functions returns the error
invalid input syntax for type double precision: "(0,0,0)"
as soon the select statement contains the line into result. If I remove this line or change the output variable from result to something of type text the functions works as expected.
Why is it not possible to assign an already to type vector casted value into a vector? Don't get it!
You do not need to (and in fact should not) create a cast from text. When you create a composite type you can cast a text to the type without any additional steps:
create type my_record as(
x int,
y int,
z int
);
select '(1,2,3)'::my_record;
my_record
-----------
(1,2,3)
(1 row)
If you want to use jsonb, create a cast from jsonb to the type:
create or replace function my_record_from_jsonb(obj jsonb, out result my_record)
strict immutable language plpgsql as $$
begin
select (obj->>'x')::int, (obj->>'y')::int, (obj->>'z')::int
into result;
end
$$;
create cast (jsonb as my_record)
with function my_record_from_jsonb(jsonb);
select '{"x":1, "y":2, "z":3}'::jsonb::my_record;
my_record
-----------
(1,2,3)
(1 row)
Do not try to interpret text literals in two different ways. If you want to use jsonb syntax, use jsonb type. Creating a custom implicit cast from text is particularly unreasonable. Read in the documentation::
It is wise to be conservative about marking casts as implicit. An overabundance of implicit casting paths can cause PostgreSQL to choose surprising interpretations of commands, or to be unable to resolve commands at all because there are multiple possible interpretations. A good rule of thumb is to make a cast implicitly invokable only for information-preserving transformations between types in the same general type category. For example, the cast from int2 to int4 can reasonably be implicit, but the cast from float8 to int4 should probably be assignment-only. Cross-type-category casts, such as text to int4, are best made explicit-only.
I have created custom data type. In that I have given alias name of the one field. you will get that in body of the function below.
create type voucher as (
ori numeric, RECEIPT_NO numeric
, receipt_date timestamp with time zone, reg_no character varying
, patient_name character varying, tot_refund_bill_amount double precision
, username character varying );
Thea above statement completes successfully.
Then I want to create a function:
create or replace function billing.voucher_receipt (in_from_date timestamp with time zone, in_to_date timestamp with time zone)
returns setof voucher as $$
declare
out_put voucher%rowtype;
begin
return query(select C.receipt_no as ori ,A.RECEIPT_NO, receipt_date , A.reg_no, patient_name, tot_refund_bill_amount, username
from billing.tran_counter_receipt as a inner join mas_user as b on a.ent_by=b.uid AND cash_book='REFUND'
INNER JOIN billing.tran_BILL AS C ON C.REG_NO=A.REG_NO AND C.CASH_BOOK='GCASH' where receipt_date>=in_from_date and receipt_date<=in_to_date);
end;$$
LANGUAGE plpgsql
Executes without problem.
But when I call it with input like this:
select * from voucher_receipt ('2014-09-25 11:42:44.298346+05:30'
, '2014-09-29 11:03:47.573049+05:30')
it shows an error:
ERROR: function voucher_receipt(unknown, unknown) does not exist
LINE 1: select * from voucher_receipt ('2014-09-25 11:42:44.298346+0...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Can any one help me out from this?
Explain error
You created your function in the schema billing with:
create or replace function billing.voucher_receipt( ...
Then you call without schema-qualification:
select * from voucher_receipt ( ...
This only works while your current setting for search_path includes the schema billing.
Better function
You don't need to create a composite type. Unless you need the same type in multiple places just use RETURNS TABLE to define the return type in the function:
CREATE OR REPLACE FUNCTION billing.voucher_receipt (_from timestamptz
, _to timestamptz)
RETURNS TABLE (
ori numeric
, receipt_no numeric
, receipt_date timestamptz
, reg_no varchar
, patient_name varchar
, tot_refund_bill_amount float8
, username varchar) AS
$func$
BEGIN
RETURN QUERY
SELECT b.receipt_no -- AS ori
, cr.RECEIPT_NO
, ??.receipt_date
, cr.reg_no
, ??.patient_name
, ??.tot_refund_bill_amount
, ??.username
FROM billing.tran_counter_receipt cr
JOIN billing.tran_bill b USING (reg_no)
JOIN mas_user u ON u.uid = cr.ent_by
WHERE ??.receipt_date >= _from
AND ??.receipt_date <= _to
AND b.CASH_BOOK = 'GCASH'
AND ??.cash_book = 'REFUND'
END
$func$ LANGUAGE plpgsql;
Notes
Don't call your parameters "date" while they are actually timestamptz.
RETURN QUERY does not require parentheses.
No need for DECLARE out_put voucher%rowtype; at all.
Your format was inconsistent and messy. That ruins readability and that's also where bugs can hide.
This could just as well be a simple SQL function.
Column names in RETURNS TABLE are visible in the function body almost everywhere. table-qualify columns in your query to avoid ambiguities (and errors). Replace all ??. I left in the code, where information was missing.
Output column names are superseded by names in the RETURNS declaration. So AS ori in the SELECT list is just documentation in this case.
Why schema-qualify billing.tran_bill but not mas_user?
I want to calculate the average number from a column in PostgreSQL
SELECT AVG(col_name)
From TableName
It gives me this error:
ERROR: function avg (character varying) does not exist
LINE 1: SELECT AVG(col_name)
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Store numbers in a numeric field, an integer, decimal or whatever. But not in a text/varchar field.
Check the manual for all numeric data types.
Nasty workaound: CAST some records to a numeric value and keep others as text. Example:
/*
create temp table foo AS
SELECT x FROM (VALUES('x'),('1'),('2')) sub(x);
*/
WITH cte AS (
SELECT
CASE
WHEN x ~ '[0-9]' THEN CAST(x AS decimal) -- cast to numeric field
END AS num,
CASE
WHEN x ~ '[a-zA-Z]' THEN x
END AS a
FROM foo
)
SELECT AVG(num), COUNT(a) FROM cte;
I'm trying to create an user-defined function in Postgresql:
CREATE FUNCTION get_balance(user_id integer, statuses integer[]) RETURNS INTEGER
AS $$
select SUM(table1.credit)
from table1
inner join table2
on table2.field1 = table1.id
inner join table3
on table3.field1 = table2.id
where table3.status_id in (statuses); $$
LANGUAGE SQL;
The error is:
ERROR: operator does not exist: integer = integer[]
LINE 11: where table3.status_id in (statuses); $$
What am I doing wrong?
This:
table3.status_id in (statuses)
can be simplified for the example into:
regress=> SELECT 1 IN (ARRAY[1,2,3]);
ERROR: operator does not exist: integer = integer[]
LINE 1: SELECT 1 IN (ARRAY[1,2,3]);
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
... but IN expects a literal list, eg:
regress=> SELECT 1 IN (1, 2, 3);
Since you want to pass an array, you'll want to use = ANY(...) which expects an array input:
regress=> SELECT 1 = ANY (ARRAY[1,2,3]);
?column?
----------
t
(1 row)