Same name attributes in select list in pg-promise - pg-promise

Is it possible to get the same name attributes in the select list (as JSON deduplicates them)?
For instance:
CREATE TABLE t1 (
id int;
);
INSERT INTO t1 VALUES(1);
INSERT INTO t1 VALUES(2);
CREATE TABLE t2 (
id int;
);
INSERT INTO t2 VALUES(1);
SELECT *
FROM t1 LEFT JOIN t2 ON t1.id = t2.id
should return:
id id
-----
1 1
2 null
but will return instead:
id
---
1
null
I'm trying to build a web-based SQL editor, and this is kind of a showstopper.

Sorry, found it, it was solved in:
pg: https://github.com/brianc/node-postgres/pull/393
and subsequently in pg-promise: https://github.com/vitaly-t/pg-promise/releases/tag/v.4.0.5
One can use rowMode argument to get results as an array:
http://vitaly-t.github.io/pg-promise/PreparedStatement.html#rowMode

Related

How to add items to local function array in postgress?

I need to do multiple inserts in the table that number depends on how many records we got from select. I need to iterate over records from select and then insert them to another table. I want to get all new Ids from insert to array to use them later in the following inserts, how can I do this?
I can't collect them using select after insert, because there can be old records.
for record in (select test, test1, test2
from public.a
join public.b on a.reg_id = b.id
where a.id = arg_id) loop
(INSERT into public.c
( a, b, c)
(select test, test1, test2
from record)--need to get ids from this
end loop;
---
some block where I have old_ids
---
--to insert them there
insert into public.d(d,e,f,g)values(..,..,old_id,(id from previous insert))
upd
Tried to make like this:
with a2 as(
INSERT INTO public.reg
(name_, code, state)
(select a.secondname, a.code, b.state_name--multiple rows from select
from public.client a
left join public.states b on a.state_id = b.id
where a.id = id_p) RETURNING id
)
INSERT INTO public.request
(phone, address, qty, prod_id, reg_id)
(select phone, address, qty, prod_id, (select id from a2)--maybe something wrong there, but error happend before
from public.shp a
where a.id = id_p);
but getting an error: more than one row returned by a subquery used as an expression
Demonstration of using the result of a query:
\i tmp.sql
CREATE TABLE aa(aa integer not null primary key);
CREATE TABLE bb(bb integer not null primary key);
CREATE TABLE cc(cc integer not null primary key);
WITH x0 AS (
INSERT INTO aa(aa) values (1),(2),(3)
returning aa
)
, x1 AS (
INSERT INTO bb(bb)
SELECT aa*aa from x0
returning bb
)
, x2 AS (
INSERT INTO cc(cc)
SELECT bb*bb from x1
returning cc
)
-- main query
SELECT *
FROM x2
;
-- Check cc
SELECT *
FROM cc
;
Output:
DROP SCHEMA
CREATE SCHEMA
SET
CREATE TABLE
CREATE TABLE
CREATE TABLE
cc
----
1
16
81
(3 rows)
cc
----
1
16
81
(3 rows)

how to sort rows according to multiple dependencies

The table has many columns, but for the problematic part let's assume only two, [ID] and [dependency].
[Dependency] means which [ID]s should be listed before this [ID].
Each row has its unique [ID] but it might have none, one or more dependencies in the [Dependency] column
ID
Dependency
1
4
2
null
3
1,2
4
2
5
1,2,4
Expected Result
ID
Dependency
2
null
4
2
1
4
3
1,2
5
1,2,4
I have no prior experience in Postgres, I found this very useful:
SELECT aa.dep_id::integer FROM unnest(string_to_array(ss.dependency, ',')) aa(dep_id)
But still, I can't make it right.
EDIT: Added one row with 3 dependencies'
http://sqlfiddle.com/#!15/894c3/4
Use a recursive CTE:
WITH RECURSIVE o AS (
SELECT ss.id, ss.dependency,
1 AS level
FROM ss
WHERE dependency IS NULL
UNION ALL
SELECT ss.id, ss.dependency,
o.level + 1
FROM ss
JOIN o
ON o.id IN (SELECT x
FROM unnest(ss.dependency) AS x(x)
)
)
SELECT o.id, o.dependency
FROM o
GROUP BY o.id, o.dependency
ORDER BY max(o.level);
My working solution, I hope it can be improved
DO $do$
DECLARE v_RowCountInt Int;
--copy all values to temp table
begin
--This is the origin table, all rows to sort
drop table if exists _tempAll;
create temp table _tempAll as select id, dependency from XXXXX;
-- create temp table for results
drop table if exists _tempSort;
create temp table _tempSort (
id integer
,dependency varchar
,pos serial primary key);
-- move all IDs with no depencencies
WITH tmp AS (DELETE FROM _tempAll where dependency is null RETURNING id, dependency)
INSERT INTO _tempSort ( id, dependency)
SELECT id, dependency FROM tmp;
GET DIAGNOSTICS v_RowCountInt = ROW_COUNT;
while v_RowCountInt>0 loop
-- move rows with all dependencies met
WITH tmp AS (DELETE FROM _tempAll a
where a.id in(SELECT a.id FROM _tempSort s inner join _tempAll a on
s.id in (select split.dep_sid::integer from unnest(string_to_array(a.dependency, ',')) split(dep_sid))
group by a.id, a.dependency
-- verify all dependencies are already sorted
having count(*)=(CHAR_LENGTH(a.dependency) - CHAR_LENGTH(REPLACE(a.dependency, ',', ''))+1))
RETURNING a.id, a.dependency)
INSERT INTO _tempSort (id, dependency)
SELECT id, dependency FROM tmp;
GET DIAGNOSTICS v_RowCountInt = ROW_COUNT;
end loop;
end;
$do$

Inner join with table that does not contain any record fails?

I have query in which I have applied inner join, it works fine if the joining table on right side has some records, but inner joins return nothing when joining table has 0 (zero) records, and I understand it bcz it has nothing to join on.
I want the records from tbl11 if record has status=1 in tbl11 or if that record exist in tbl12 then it must have status=1, if tbl12.status=0, then that record is not needed.
Table structure
create table tbl11
(
tbl11_id serial primary key,
name character varying,
status integer
)
insert into tbl11(name, status) values('Tony',1),
('Jony',1),
('Sneha',1),
('Aakriti',0)
create table tbl12
(
tbl12_id serial primary key,
tbl11_id integer,
name character varying,
status integer
)
Here is what, I have tried till now
select t1.tbl11_id, t1.name, t1.status from tbl11 t1
inner join tbl12 t2 on t1.tbl11_id = t2.tbl11_id or t1.tbl11_id !=t2.tbl11_id
where t1.status=1 and t2.status=1
It gives no output as tbl12 doesn't have any data.
Then I read about case in postgres and tried this
select case
when
select exists (select 1 from tbl12)
Then
select t1.tbl11_id, t1.name, t1.status from tbl11 t1
inner join tbl12 t2 on t1.tbl11_id = t2.tbl11_id or t1.tbl11_id !=t2.tbl11_id
where t1.status=1 and t2.status=2
else
select tbl11_id, name, status from tbl11 where status=1
But it gives error as
ERROR: syntax error at or near "select"
LINE 3: select exists (select 1 from tbl12)
this is the simple query
select * from tbl11 where status=1 and tbl11_id not in (select tbl11_id from tbl12 where status=0);
DEMO

Postgres join involving tables having join condition defined on an text array

I have two tables in postgresql
One table is of the form
Create table table1(
ID serial PRIMARY KEY,
Type []Text
)
Create table table2(
type text,
sellerID int
)
Now i want to get all the rows from table1 which are having type same that in table2 but the problem is that in table1 the type is an array.
In case the type in the table has an identifiable delimiter like ',' ,';' etc. you can rewrite the query as regexp_split_to_table(type,',') or versions later than 9.5 unnest function can be use too.
For eg.,
select * from
( select id ,regexp_split_to_table(type,',') from table1)table1
inner join
select * from table2
on trim(table1.type) = trim(table2.type)
Another good example can be found - https://www.dbrnd.com/2017/03/postgresql-regexp_split_to_array-to-split-string-using-different-delimiters/
SELECT
a[1] AS DiskInfo
,a[2] AS DiskNumber
,a[3] AS MessageKeyword
FROM (
SELECT regexp_split_to_array('Postgres Disk information , disk 2 , failed', ',')
) AS dt(a)
You can use the ANY operator in the JOIN condition:
select *
from table1 t1
join table2 t2 on t2.type = any (t1.type);
Note that if the types in the table1 match multiple rows in table2, you would get duplicates (from table1) because that's how a join works. Maybe you want an EXISTS condition instead:
select *
from table1 t1
where exists (select *
from table2 t2
where t2.type = any(t1.type));

PostgreSql: why this update works incorrectly?

There is table t1 in what I need to replace id with new value.
The 2nd table t_changes contains substitutions
old_id->new_id.
But when I do UPDATE the t1 contains the same new id value for all records.
What is incorrect?
The same update works in T-SQL successfully.
drop table t1;
drop table t2;
drop table t_changes;
create table t1
(id INT,name text, new_id INT default(0));
create table t_changes
(old_id INT,new_id int)
insert into t1(id,NAME)
VALUES (1,'n1'),(2,'n2'),(3,'n3');
insert into t_changes(old_id,new_id)
values(1,11),(2,12),(3,13),(4,13)
select * from t1;
select * from t_changes;
-------!!!!
update t1
set new_id = n.new_id
from t1 t
inner join t_changes n
on n.old_id=t.id;
select * from t1
------------------------------
"id" "name" "new_id"
-----------------
"1" "n1" "11"
"2" "n2" "11"
"3" "n3" "11"
This is your Postgres update statement:
update t1
set new_id = n.new_id
from t1 t inner join
t_changes n
on n.old_id = t.id;
The problem is that the t1 in the update refers to a different t1 in the from. You intend for them to be the same reference. You can do this as:
update t1
set new_id = n.new_id
from t_changes n
where n.old_id = t.id;
Your syntax is fairly close to the syntax supported by some other databases (such as SQL Server). However, for them, you would need to use the table alias in the update:
update t
set new_id = n.new_id
from t1 t inner join
t_changes n
on n.old_id = t.id;
How about doing this instead:
update t1
set new_id = (SELECT new_id FROM t_changes WHERE old_id=id);
Note that if for some row in t1 there is no corresponding row in t_changes, this will change t1.new_id to NULL.