How to get multiple table data in one query in posgresql JSONB data type - postgresql

How can I Fetch table data in one query? I have below tables:
Tabel Name: calorieTracker
Creat Table calorieTracker(c_id serial NOT NULL PRIMARY KEY, caloriesConsumption jsonb);
INSERT INTO public."calorieTracker" ("caloriesConsumption")
VALUES ('[{"C_id":"1",,"calorie":88,"date":"19/08/2020"},{"C_id":2,"date":"19/08/2020","calorie":87}]');
Table Name: watertracker
create table watertracker(wt_id serial not null primary key, wt_date varchar, wt_goal float,wt_cid int);
INSERT INTO public.watertracker (wt_id,wt_date,wt_goal,wt_cid)
VALUES (2,'2020-08-19',5.5,2);
What I am looking here I want to write query where date is 19/08/2020(in calorieTracker table and water tracker table) and wt_cid is 2(water tracker table) and c_id is 2(calorieTracker table) then return data.

As you have not mentioned what output you want, so i am assuming you want JSON object from caloriesConsumption which matches the condition mentioned in the question:
based on above assumption try this query:
with cte as (
select
c_id,
jsonb_array_elements("caloriesConsumption") "data"
from "calorieTracker"
)
select
t1.*
from cte t1 inner join watertracker t2
on t2.wt_cid=cast(t1.data->>'c_id' as int)
and t2.wt_date=t1.data->>'date'
if you want the result from watertracker then just replace t1.* with t2.*.

Related

Postgres - Oracle data type conversion

We have a foreign table that is connecting to Oracle. In Oracle, the columns are:
ticker: VARCHAR2(5)
article_id: NUMBER
In Postgres, we have tried to create the article_id as INTEGER and NUMERIC, but every time we try and query we get this error:
column "article_id" of foreign table "latest_article_id" cannot be converted to or from Oracle data type
How can we create this foreign table so we can query it? The article_id is a number, so is there additional commands we must use?
We are on Postgres 10.10.
CREATE FOREIGN TABLE latest_article_id
(ticker VARCHAR,
article_id NUMERIC)
SERVER usercomm
OPTIONS ( table '(SELECT article_id, ticker
FROM (SELECT a.article_id, t.ticker,
ROW_NUMBER() OVER (PARTITION BY t.ticker
ORDER BY a.publish_date DESC NULLS LAST) AS rnum
FROM tickers t, article_tickers at, articles a
WHERE t.ticker_id = at.ticker_id
AND at.article_id = a.article_id
AND a.status_id = 6
AND a.pull_flag = ''Y'')
WHERE rnum = 1)');

Can I refer to data in jsonb table if no matching field in cross join table

I have json data in table that I use to insert new data into final table as follows
CREATE TABLE musicbrainz.acoustid_track (
id int NOT NULL,
created timestamp with time zone DEFAULT current_timestamp,
gid uuid NOT NULL,
new_id varchar(30)
);
CREATE TABLE musicbrainz.acoustid_track_json (
data jsonb
);
......
tables loaded
......
The json column data is visible in the query and you can refer to it in the WHERE clause, e.g.:
insert into musicbrainz.acoustid_track
select id, created, gid, new_id
from musicbrainz.acoustid_track_json
cross join jsonb_populate_record(null::musicbrainz.acoustid_track, data);
and this works except acoustid_track_json can contains new records or replacement records, and this is detemrined by if they have an updated field
e.g
New record
{"id":67028798,"gid":"18575a2d-bc9c-48c0-b5d7-f815b97421ed","created":"2020-02-03T00:02:11.315629+00:00"}
Updated record
{"id":66277512,"gid":"a31e1ecc-af48-4b8f-ba65-de5187a5c9a7","new_id":65603612,"created":"2019-11-17T12:37:49.81505+00:00","updated":"2020-02-03T13:12:58.043985+00:00"}
but I cant seem to modify INSERT to refer to updated field, possibly because no updated field in the final table, how do I do this.
The json column data is visible in the query and you can refer to it in the WHERE clause, e.g.:
insert into musicbrainz.acoustid_track
select id, created, gid, new_id
from musicbrainz.acoustid_track_json
cross join jsonb_populate_record(null::musicbrainz.acoustid_track, data)
where data->'updated' is null;

How can I bulk insert rows only if a compound primary key don't already exist? [AWS Redshift]

in Amazon Redshift I try to do a bulk insert value in a table from a temp table.
However I only want to insert the values where a compound of values (primary key) not exist in the table, to avoid adding duplicate.
Below the DDL of the table
• clusters_typologies table (table when i want to insert data)
create table if not exists clusters.clusters_typologies
(
cluster_id BIGINT,
typology_id BIGINT,
semantic_id BIGINT,
primary key (cluster_id, typology_id, semantic_id)
);
Temp Table is create with query below and after that all field are correctly inserted.
CREATE TEMPORARY TABLE temporary (
cluster_id bigint,
typology_name varchar(100),
typology_id bigint,
semantic_name varchar(100),
semantic_id bigint
);
Now when i try to insert with that query
INSERT INTO clusters.clusters_typologies (cluster_id, typology_id,semantic_id)
(SELECT temp.cluster_id, temp.typology_id, temp.semantic_id
FROM temporary temp
WHERE NOT EXISTS(SELECT 1
FROM clusters_typologies
where cluster_id = temp.cluster_id
and typology_id = temp.typology_id
and semantic_id = temp.semantic_id));
I got this error and i cannot figured out how to make it work.
Invalid operation: This type of correlated subquery pattern is not supported due to internal error;
Anyone know how to fix or how is the best way to insert in a table with a compound key avoiding duplicate.
Thanks.
To upsert follow this guide
https://docs.aws.amazon.com/redshift/latest/dg/c_best-practices-upsert.html
and note that certain types of correlated subquery are not allowed in redshift - that is the cause of your error
see
https://docs.aws.amazon.com/redshift/latest/dg/r_correlated_subqueries.html
After some attempt I figured out how to do an insert from a temp table, and check from a compound primary key to avoid duplicate.
Basically from AWS documentation that #Jon Scott as sent, I understand that use outer table in inner select is not supported from Redshift.
I solve using a left join and check if the joining column is null.
Below the query I use now.
INSERT INTO clusters.clusters_typologies (cluster_id, typology_id, semantic_id)
(SELECT temp.cluster_id, temp.typology_id, temp.semantic_id
FROM aaaa temp
LEFT JOIN clusters.clusters_typologies clu_typ ON temp.cluster_id = clu_typ.cluster_id AND
temp.typology_id = clu_typ.typology_id AND
temp.semantic_id = clu_typ.semantic_id
WHERE clu_typ.cluster_id IS NULL
AND clu_typ.typology_id IS NULL
AND clu_typ.semantic_id IS NULL);

PostgreSQL count other values of ID that have the same value of other column

Let's say we have the following table that stores id of an observation and its address_id. You can create the table with the following code:
drop table if exists schema.pl_address_cnt;
create table schema.pl_address_cnt (
id serial,
address_id int);
insert into schema.pl_address_cnt(address_id) values
(100), (101), (100), (101), (100), (125), (128), (200), (200), (100);
My task is to count for each id how many other ids (thus -1) have the same address_id. I've come up with a solution that turns out to be quite expensive (explain) on the original dataset. I wonder whether my solution can be somehow optimised.
with tmp_table as (select address_id
, count(distinct id) as id_count
from schema.pl_address_cnt
group by address_id
)
select id
, id_count - 1
from schema.pl_address_cnt as pac
left join tmp_table as tt on tt.address_id=pac.address_id;
You can try to omit the CTE and do a self left join on common address but different ID and then aggregate this.
SELECT pac1.id,
count(pac2.id)
FROM pl_address_cnt pac1
LEFT JOIN pl_address_cnt pac2
ON pac1.address_id = pac2.address_id
AND pac1.id <> pac2.id
GROUP BY pac1.id
ORDER BY pac1.id;
For performance you can try indexes on (address_id, id) and (id).

Use COPY FROM command in PostgreSQL to insert in multiple tables

I'm trying to use the performance of COPY FROM command in PostgreSQL to get all data of 1 table of a CSV file (CSV -> table1) and I need to insert other data, but, in a new table. I will need of a primary key of first table to put as a foreign key in second table.
Example:
I need to insert 1,000,000 of names in table1 and 500,000 of names in table2, but, all names in table2 reference to 1 tuple in table1.
CREATE TABLE table1 (
table1Id bigserial NOT NULL,
Name varchar(100) NULL,
CONSTRAINT table1Id PRIMARY KEY (table1Id)
);
CREATE TABLE table2 (
table2Id bigserial NOT NULL,
Other_name varchar(100) NOT NULL
table1_table1Id int8 NOT NULL,
CONSTRAINT table2_pk PRIMARY KEY (table2Id)
);
Command COPY does not allow table manipulations while copying data (such as look up to other table for fetching proper foreign keys to insert). To insert into table2 ids for corresponding rows from table1 you need to drop NOT NULL constraint for that field, COPY data and then UPDATE that fields separately.
Assuming table1 and table2 tables can be joined by table1.Name = table2.Other_name, the code is:
Before COPY:
ALTER TABLE table2 ALTER COLUMN table1_table1Id DROP NOT NULL;
After COPY:
UPDATE table2 SET table2.table1_table1Id = table1.table1Id
FROM table1
WHERE table1.Name = table2.Other_name;
ALTER TABLE table2 ALTER COLUMN table1_table1Id SET NOT NULL;