Pass String in Postgres Query - postgresql

I am using Postgresql 9.3 and what I am trying to do is Passing column names as string into my query. For newtable my column number can be dynamic sometimes it might be 3 or more for which I am trying to select column from another table and pssing relut of my query as string in the existing query
Please help how can i do this
select * from crosstab (
'select "TIMESTAMP_S","VARIABLE","VALUE" from archieve_export_db_a3 group by 1,2,3 order by 1,2',
'select distinct "VARIABLE" From archieve_export_db_variables order by 1'
) AS newtable (TIMESTAMP_S int,_col1 integer,_col2 integer);

Related

Postgresql : ERROR: in creating temp table with list object values

I am writing a Postgresql function (using pgAdmin GUI) that will be invoked from my Spring Boot application with java list object as parameters
My actual requirement is mentioned here and with the suggestions to create a temp table with list values to optimize query, following is the Postgres function which I have tried by referring from here:
CREATE FUNCTION public."getInventory"("vals1Arg" character varying[], "vals2Arg" character varying[])
RETURNS "INVENTORY"
LANGUAGE 'sql'
AS
$BODY$
// I assume the below two lines create two temp tables and populate the table
with my list object values
CREATE TEMP TABLE t1 AS
SELECT * FROM VALUES(vals1Arg)
CREATE TEMP TABLE t2 AS
SELECT * FROM VALUES(vals2Arg)
SELECT * FROM "INVENTORY"
where "COLUMN_1" in (select * from t1)
and "COLUMN_2" in (Select * from t2);
$BODY$;
Following is the code snippet by how I am invoking postgres function
#Query(nativeQuery = true, value = "select \"getInventory\" (:vals1Arg,:vals2Arg)")
List<Inventory> getInventoryInfo(List<String> vals1Arg, List<String> vals2Arg);
As the list is going to be huge, I am creating a temporary table with values from the list object paramaters and use it in my select query
Thank you in advance !!
There are several problems:
The syntax of the CREATE TABLE ... AS should be
CREATE TABLE ... AS
SELECT * FROM (VALUES (...)) AS alias;
instead of
CREATE TABLE ... AS
SELECT * FROM VALUES (...);
You need these parentheses and the alias.
The subselect in the query won't work, as it compares a varchar (COLUMN_1) with a varchar[] (the column of the temporary table).
To make that work, you'd have to
SELECT * FROM "INVENTORY"
WHERE "COLUMN_1" = ANY (SELECT * FROM t1);
If you want to create temporary tables rather than using the array directly in the SELECT, you had better
CREATE TEMP TABLE t1 AS
SELECT * FROM unnest(vals1Arg) AS u(c);
CREATE TEMP TABLE t2 AS
SELECT * FROM unnest(scomoIdList) AS u(c);
ANALYZE t1, t2;
RETURN QUERY SELECT * FROM "INVENTORY"
JOIN t1 ON "INVENTORY"."COLUMN_1" = t1.c
JOIN t2 ON "INVENTORY"."COLUMN_2" = t2.c;
This assumes that the lists don't contain duplicate entries.

Output Inserted.id equivalent in Postgres

I am new to PostgreSQL and trying to convert mssql scripts to Postgres.
For Merge statement, we can use insert on conflict update or do nothing but am using the below statement, not sure whether it is the correct way.
MSSQL code:
Declare #tab2(New_Id int not null, Old_Id int not null)
MERGE Tab1 as Target
USING (select * from Tab1
WHERE ColumnId = #ID) as Source on 0 = 1
when not matched by Target then
INSERT
(ColumnId
,Col1
,Col2
,Col3
)
VALUES (Source.ColumnId
,Source.Col1
,Source.Col2
,Source.Col3
)
OUTPUT INSERTED.Id, Source.Id into #tab2(New_Id, Old_Id);
Postgres Code:
Create temp table tab2(New_Id int not null, Old_Id int not null)
With source as( select * from Tab1
WHERE ColumnId = ID)
Insert into Tab1(ColumnId
,Col1
,Col2
,Col3
)
select Source.ColumnId
,Source.Col1
,Source.Col2
,Source.Col3
from source
My query is how to convert OUTPUT INSERTED.Id in postgres.I need this id to insert records in another table (lets say as child tables based on Inserted values in Tab1)
In PostgreSQL's INSERT statements you can choose what the query should return. From the docs on INSERT:
The optional RETURNING clause causes INSERT to compute and return value(s) based on each row actually inserted (or updated, if an ON CONFLICT DO UPDATE clause was used). This is primarily useful for obtaining values that were supplied by defaults, such as a serial sequence number. However, any expression using the table's columns is allowed. The syntax of the RETURNING list is identical to that of the output list of SELECT. Only rows that were successfully inserted or updated will be returned.
Example (shortened form of your query):
WITH [...] INSERT INTO Tab1 ([...]) SELECT [...] FROM [...] RETURNING Tab1.id

dynamically select the most occurring value from a column which occurs in multiple tables

The Customer, Musician, and Staff tables in my database include a column called FirstName. The query below returns the most occurring FirstName in those three tables and returns multiple FirstNames if more than one FirstNames occurs the same amount of times.
WITH AllFirstNames AS (
SELECT FirstName
FROM Customer
UNION ALL
SELECT FirstName
FROM Musician
UNION ALL
SELECT FirstName
FROM Staff
), FirstNameOccurrences AS (
SELECT FirstName,
COUNT(*) AS Occurrences
FROM AllFirstNames
GROUP BY FirstName
)
SELECT FirstName AS MostOccurringFirstNames
FROM AllFirstNames
WHERE FirstName IN (
SELECT FirstName
FROM FirstNameOccurrences
WHERE Occurrences IN (
SELECT MAX(Occurrences)
FROM FirstNameOccurrences
)
)
GROUP BY MostOccurringFirstNames;
This only works if the tables which include the FirstName column are specified in the query which returns the temporary AllFirstNames table. If a new table with a FirstName column is added to the database, then this query will have to be updated manually. What do I need to do to the query which returns the temporary AllFirstNames table for it to dynamically UNION ALL FirstName columns from all tables which include a FirstName column? I understand that this will only work if the same naming convention is used throughout the databases lifetime.
The query below lists all the tables that include a FirstName column, but I don't know where to go from there.
SELECT table_name
FROM information_schema.columns
WHERE column_name = 'FirstName';
This does sound like a strange database design, but you can do that by creating a function that iterates over all tables.
The following function counts the distinct values per table.
create or replace function count_names()
returns table(tablename text, firstname text, occurrences bigint)
as
$$
declare
l_row record;
begin
for l_row in select distinct table_schema, table_name, column_name
from information_schema.columns
where table_schema = 'public'
and column_name = 'firstname'
loop
return query execute
format('select %L as tablename, cast(%I as text), count(*) occurrences from %I.%I group by %I',
l_row.table_name, l_row.column_name, l_row.table_schema, l_row.table_name, l_row.column_name);
end loop;
end;
$$
language plpgsql;
The above runs a count()/group by for every table that has a column named firstname in the schema public. The result can then be summed. I included the source table name in the result for debugging purposes, but it's not really needed.
With that function you can do something like this:
select firstname, sum(occurrences) num_names
from count_names()
order by num_names desc
limit 10;
Dynamic SQL is best created using the format() function to properly deal with identifiers. The column and table names you used in your question suggests you created them using the dreaded double quotes ("FirstName" is something different than FirstName) - you should really rethink that. Avoid those dreaded double quotes in SQL

How to combine multiple tables together in postgresql that have the same columns but in different order?

I have multiple tables that all have the same columns, but in different order. I want to merge them all together. I've created an empty table with the standard columns in the order I would like. I've tried inserting with
insert into master_table select * from table1;
but that doesn't work because of the differing column order - some of the values end up in the wrong columns. What is the best way to create one table out of them all in the order specified in my empty master table?
If you are dealing with many columns and many tables, you can use the information_schema to get the columns. You can loop through all the tables you want to insert from and run this in a plpgsql procedure, replacing table1 with a variable:
EXECUTE (
SELECT
'insert into master_table
(' || string_agg(quote_ident(column_name), ',') || ')
SELECT ' || string_agg('p.' || quote_ident(column_name), ',') || '
FROM table1 p '
FROM information_schema.columns raw
WHERE table_name = 'master_table');
just indicate the proper order in the select
instead of
select *
if you want 3 field on second posiition.
select field1, field3, field2
or you can use the INSERT sintaxis
INSERT INTO master_table (field1, field3, field2)
SELECT *

DB2 Query issue

SELECT
Q."COLUMN1"
FROM
(SELECT
"COLUMN1",
CAST ((SELECT CAST (RTRIM (PARAM) AS VARCHAR(50)) FROM TABLE_VIEW WHERE PARAM_ID = :ID) AS VARCHAR(50)) AS "COLUMN2"
FROM ("TABLE1")Q
WHERE
RTRIM(CAST("COLUMN1" AS CHAR(10))) IN (SELECT VALUE_1 FROM TABLE (SPLIT_PARAMS(CAST(Q."COLUMN2" AS VARCHAR(50)),',',5)))
COLUMN2 gets its value from a separate table based on the input provided at run time.
The filter used in the query consists of a used defined table valued function that is used to split the comma separated valued to individual values.
The query throws the error message as:
"FUNCTION NOT SUPPORTED. SQLCODE=-270, SQLSTATE=42997"
Can anyone help me find the cause of the issue.