Postgresql remove integer value on particular index - postgresql

I have integer array {0,23,1,29,0,15,1} postgres(V 9.3.6) and i want to remove particular element which highlighted above using it's index for example it's 3 as of now i get those element index using function idx
CREATE OR REPLACE FUNCTION idx(anyarray, anyelement)
RETURNS int AS
$$
SELECT i FROM (
SELECT generate_series(array_lower($1,1),array_upper($1,1))
) g(i)
WHERE $1[i] = $2
LIMIT 1;
$$ LANGUAGE sql IMMUTABLE;
But I'm unable to found any built in function in postgres which allows removal by using index.

create or replace function idx(the_array anyarray, idx integer)
returns anyarray as $$
select array_agg(a order by i)
from (
select
generate_series(1, array_upper(the_array, 1)),
unnest(the_array)
) s(i, a)
where i != idx
; $$ language sql;
select idx(array[0,23,1,29,0,15,1], 3);
idx
------------------
{0,23,29,0,15,1}

Related

Function to select table rows based on certain conditions

create table my_table(x int, y int);
create function get_rows()
returns table (lie my_table) as $$
begin
-- 1 First try
--select * from my_table where x < 0;
-- 2 If empty then try
--select * from my_table where y < 0;
end; $$
language plpgsql;
How to implement a function that selects rows based on condition 1, but if such rows don't exists then select based on condition 2. If nether conditions can be satisfied then return an empty table.
You can us "IF EXISTS" to test the first condition. Then depending on the result use RETURN Query for the appropriate select;
create or replace function get_rows()
returns table (lie my_table)
language plpgsql
as $$
begin
-- 1 First try
if exists (select null from my_table where x < 0)
then
return query
select * from my_table
where x < 0;
-- 2 If empty then try
else
return query
select * from my_table
where y < 0;
end if;
end; $$;

In clause in postgres

Need Output from table with in clause in PostgreSQL
I tried to make loop or ids passed from my code. I did same to update the rows dynamically, but for select I m not getting values from DB
CREATE OR REPLACE FUNCTION dashboard.rspgetpendingdispatchbyaccountgroupidandbranchid(
IN accountgroupIdCol numeric(8,0),
IN branchidcol character varying
)
RETURNS void
AS
$$
DECLARE
ArrayText text[];
i int;
BEGIN
select string_to_array(branchidcol, ',') into ArrayText;
i := 1;
loop
if i > array_upper(ArrayText, 1) then
exit;
else
SELECT
pd.branchid,pd.totallr,pd.totalarticle,pd.totalweight,
pd.totalamount
FROM dashboard.pendingdispatch AS pd
WHERE
pd.accountgroupid = accountgroupIdCol AND pd.branchid IN(ArrayText[i]::numeric);
i := i + 1;
end if;
END LOOP;
END;
$$ LANGUAGE 'plpgsql' VOLATILE;
There is no need for a loop (or PL/pgSQL actually)
You can use the array directly in the query, e.g.:
where pd.branchid = any (string_to_array(branchidcol, ','));
But your function does not return anything, so obviously you won't get a result.
If you want to return the result of that SELECT query, you need to define the function as returns table (...) and then use return query - or even better make it a SQL function:
CREATE OR REPLACE FUNCTION dashboard.rspgetpendingdispatchbyaccountgroupidandbranchid(
IN accountgroupIdCol numeric(8,0),
IN branchidcol character varying )
RETURNS table(branchid integer, totallr integer, totalarticle integer, totalweight numeric, totalamount integer)
AS
$$
SELECT pd.branchid,pd.totallr,pd.totalarticle,pd.totalweight, pd.totalamount
FROM dashboard.pendingdispatch AS pd
WHERE pd.accountgroupid = accountgroupIdCol
AND pd.branchid = any (string_to_array(branchidcol, ',')::numeric[]);
$$
LANGUAGE sql
VOLATILE;
Note that I guessed the data types for the columns of the query based on their names. You have to adjust the line with returns table (...) to match the data types of the select columns.

How do i create a column 1-10 with a loop?

This is an example but I want only a column with 1-10 values without other text columns.
CREATE OR REPLACE FUNCTION somefun_recordset(param_numcount integer)
RETURNS SETOF record AS
$$
DECLARE
result text := '';
searchsql text := '';
var_match record;
BEGIN
searchsql := 'SELECT n || '' down'' As countdown, n as integer
FROM generate_series(' || CAST(param_numcount As text) || ', 1, -1) As n ';
FOR var_match IN EXECUTE(searchsql) LOOP
RETURN NEXT var_match;
END LOOP;
END;
$$
LANGUAGE 'plpgsql' IMMUTABLE;
SELECT r.n , r.countdown
FROM somefun_recordset(10)
As r(countdown text, n integer)
ORDER BY r.n;
How do I create a loop in postgres?
From your current description, you seem to be over-complicating this.
As described in the Postgres manual, the generate_series function can generate a column of values from 10 to 1, like so:
SELECT generate_series(10, 1, -1) as n;
Or using it as a table alias rather than a column alias:
SELECT * FROM generate_series(10, 1, -1) as n;
If you wanted to wrap this in a custom function with only one parameter, it would look like this:
CREATE FUNCTION countdown(param_numcount INT) RETURNS SETOF INT LANGUAGE SQL AS $$
SELECT generate_series(param_numcount, 1, -1);
$$;
Then you would run it as:
SELECT countdown(10) as n;

postgresql: converting CTE column to array

I am trying to convert one of the columns of CTE to array. I keep on getting "syntax error at or near" followed by "ret := array(".
My objective is that the table I am returning from a_function() in example below is stored as a variable to be referred later in function. But I could not find a syntax to do so. So, instead of using CTE, if I can use something else, that would work just as nicely.
Note: I am trying this in pgAdmin III.
create or replace function a_function()
--returns int[][] as
returns table(column1 int, column2 int) as
$body$
begin
return query
select 1,2;
end;
$body$
language 'plpgsql'
;
--select * from a_function();
create or replace function test_a_function()
returns void as
$body$
declare ret int[];
begin
with ret_cte(column1, column2) as (
select * from a_function()
)
ret := array(
select column1 from ret_cte
)
;
--raise notice '%', array_to_string(ret, ',');
end;
$body$
language 'plpgsql'
;
--select test_a_function();
I am trying to convert one of the columns of CTE to array. I keep on getting "syntax error at or near" followed by "ret := array("
You could use:
ret :=array(with ret_cte(column1, column2) as (
select * from a_function()
)
select column1 from ret_cte
);
Rextester Demo
Arrays can be built and returned using the array_agg() function. For example, your second function could be written using a SQL language function that returns the array as follows:
create or replace function test_a_function()
returns int[] as
$body$
select array_agg(column1) from a_function();
$body$
language 'sql';
Alternatively, you can assign the array to a variable like this:
create or replace function test_a_function()
returns void as
$body$
declare
ret int[];
begin
select array_agg(column1)
into ret
from a_function();
raise info '%', ret;
end;
$body$
language 'plpgsql';

Greenplum/Postgres 8 function dynamic result set?

I need to write a function that returns a table with unknown number of columns.
If i receive 'None' in column input parameter then that column shouldn't be included in the output. In postgres 9+ there is a solution for this problem.
something like below:
CREATE OR REPLACE FUNCTION data_of(id integer,col1 varchar,col2 varchar, col3 varchar)
RETURNS TABLE (count_rec, dimensions text[] ) AS
$func$
DECLARE
_dimensions text := 'col1, col2, col3'; -- If i receive 'None' in input param then i exclude that from column list
BEGIN
RETURN QUERY EXECUTE format('
SELECT count(*) as count_rec,
string_to_array($1) -- AS dimensions
FROM x
WHERE id = $2'
, _dimensions)
USING _dimensions , _id;
END
$func$ LANGUAGE plpgsql;
But in Greenplum (Postgres 8.2) i could not find any. Is there any similar solution?
thanks
You have 2 options to do it: use set-returning function returning "record" or returning your custom type.
First option:
create table test (a int, b int, c int, d varchar, e varchar, f varchar);
insert into test select id, id*2, id*3, (id*4)::varchar, (id*4)::varchar, (id*4)::varchar from generate_series(1,10) id;
create or replace function test_func(column_list varchar[]) returns setof record as $BODY$
declare
r record;
begin
for r in execute 'select ' || array_to_string(column_list, ',') || ' from test' loop
return next r;
end loop;
return;
end;
$BODY$
language plpgsql
volatile;
select * from test_func(array['a','c','e']) as f(a int, c int, e varchar);
Second option:
create table test (a int, b int, c int, d varchar, e varchar, f varchar);
insert into test select id, id*2, id*3, (id*4)::varchar, (id*4)::varchar, (id*4)::varchar from generate_series(1,10) id;
create type testtype as (
a int,
c int,
e varchar
);
create or replace function test_func() returns setof testtype as $BODY$
declare
r testtype;
begin
for r in execute 'select a,c,e from test' loop
return next r;
end loop;
return;
end;
$BODY$
language plpgsql
volatile;
select * from test_func();
But I'm 99% sure you're trying to do something wrong. In Greenplum the result of function execution cannot be used as a "table" in join conditions, because the function executes on the master. You even won't be able to create a table out of the last query returning the data from your function because of this limitation
In short, this is not a recommended way to work with data in Greenplum