How to update multiple fields in two tables using inner join - postgresql

I've two tables. And I need two fields to update.
they are connected to each other with a foreign key. I would like to update the fields found in these two tables by using my inner join.
UPDATE cert
SET cert.status = 1, doc.status = 1
FROM certificates cert
INNER JOIN documents doc ON doc.data_id = cert.certificate_id
WHERE cert.status = 0 AND cert.user_id = _expert_id AND doc.data_type = 'CERTIFICATE';
The code I mentioned above allows me to update the status field in the certificates table only. In addition, I would like to update the field in the documents table

Maybe this helps:
demo:db<>fiddle
WITH cert_update AS (
UPDATE certificates cert
SET status = 1
FROM documents doc
WHERE doc.data_id = cert.certificate_id
AND cert.status = 0
AND cert.user_id = '2' -- your "_expert_id"
AND doc.data_type = 'CERTIFICATE'
RETURNING certificate_id
)
UPDATE documents doc
SET status = 1
FROM cert_update cert
WHERE doc.data_id = cert.certificate_id
AND doc.data_type = 'CERTIFICATE';
Using the WITH clause (CTE) you are able to do several updates in one query. The first one gives back the updated certificate_id which can be used in the second query.

Related

UPDATE with INNER JOIN - PostgreSQL

I have two tables one called customer and the other called referrals I need to add some numbers to two columns in table "referrals" but to know which ones, I need to refer the the table "customer" since its the one that has the group_id.
Here's an example of what I tried
UPDATE referrals AS r
SET total_coins_received = r.total_coins_received + 2, unused_ref_coins = r.unused_ref_coins + 2
FROM customer AS c
WHERE c.group_id = '1' and c.subscription_state = 'active';
This ignored my WHERE state and updated all the fields even if it didn't match the "group_id"
How can I just reference that I need to just change the ones that apply to the conditions?
This is a fiddle with an example of what is happening: https://www.db-fiddle.com/f/4jyoMCicNSZpjMt4jFYoz5/239
Add in the WHERE clause the condition that links the 2 tables:
WHERE c.cust_id = r.cust_id and c.group_id = '1' and c.subscription_state = 'active';
Without the condition c.cust_id = r.cust_id what you get is the cartesian product of referrals and the rows of customer that satisfy the conditions c.group_id = '1' and c.subscription_state = 'active' and this is why all the rows of referrals are updated.

UPDATE in postgresql with JOINS

I have a form where some input has a value that is made with this query:
SELECT e.tree.nombre
FROM d.p
JOIN e.theme ON id = id_capa
LEFT JOIN e.tree ON e.theme.id_tree = e.tree.id
WHERE id_capa = 816
e and d are schemas. The id_capa = 816 is passed as an argument to the query from the form that I'm editing. It returns a value correctly. Now I want to edit that value on my form, so I need to UPDATE but I have multiple tables, I read that I can't do an UPDATE with JOINS, how should I do that UPDATE?
In your original SQL query, the table d.p is not used, neither in SELECT nor in conditions. So it can be skipped; the query can be rewritten as:
SELECT e.tree.nombre
FROM e.theme
LEFT JOIN e.tree ON e.theme.id_tree = e.tree.id
WHERE e.theme.id = 816
Since the query selects values from table joined with LEFT JOIN, the result can be NULL, ie joined record from e.tree table can be missed. In this case there is nothing to update.
Existing matching record can be updated with the query:
UPDATE e.tree
SET nombre = <NEW_VALUE>
FROM e.theme
WHERE e.theme.id = 816 AND e.theme.id_tree = e.tree.id

more than one row returned by a subquery used as an expression in postgreSql query with IN clause

I am facing an issue with the query in postgreSql. Below is the query.
UPDATE t_e20so1_fieldrulethen AS fthen
SET c_thenfieldid = t1.c_fieldschemaid
FROM t_sys_fieldschema AS t1
WHERE fthen.c_lyrathenfieldid = t1.c_lyraid
AND fthen.c_rulefor = 5
AND t1.c_fieldtype = 18
AND t1.c_tablegroupsid IN (
CASE
WHEN fthen.c_iffieldid = t1.c_id THEN (SELECT
c_targettableid
FROM t_sys_tablegroups
WHERE c_parentid = 'c0b2f85c-bc93-466b-a54d-b1330440db98')
ELSE (SELECT c_targettableid
FROM t_sys_tablegroups
WHERE c_parentid =
'c0b2f85c-bc93-466b-a54d-b1330440db98')
END );
As per above query, i am updating t_e20so1_fieldrulethen table from t_sys_fieldschema. One of the conditions to check is t_sys_fieldschema.c_tablegroupsid should be having specific values which are in and I am fetching them from table t_sys_tablegroups.
Above query gives me error as shown below:
ERROR: more than one row returned by a subquery used as an expression
SQL state: 21000
Here, if I remove case from the query (below is what I mean) it works properly.
UPDATE t_e20so1_fieldrulethen AS fthen
SET c_thenfieldid = t1.c_fieldschemaid
FROM t_sys_fieldschema AS t1
WHERE fthen.c_lyrathenfieldid = t1.c_lyraid
AND fthen.c_rulefor = 5
AND t1.c_fieldtype = 18
AND t1.c_tablegroupsid IN (SELECT c_targettableid
FROM t_sys_tablegroups
WHERE
c_parentid = 'c0b2f85c-bc93-466b-a54d-b1330440db98')
Now I have only one select query in the "IN" clause.
I've checked that kind of case statement(two nested selects) - and it cannot be done that way. You generate two separate lists in one CASE.
One list for all records where fthen.c_iffieldid = t1.c_id and the other for ELSE statement.
As I wrote many times never use nested selects in "IN" clause. It is killing performance and causing many problems. Use "EXISTS".
As your CASE seems to be redundant (both WHEN and ELSE returns same value) change it that way and it will be faster.
UPDATE t_e20so1_fieldrulethen AS fthen
SET c_thenfieldid = t1.c_fieldschemaid
FROM t_sys_fieldschema AS t1
WHERE fthen.c_lyrathenfieldid = t1.c_lyraid
AND fthen.c_rulefor = 5
AND t1.c_fieldtype = 18
AND exists (select from t_sys_tablegroups t2
where t1.c_tablegroupsid=t2.c_targettableid
and c_parentid = 'c0b2f85c-bc93-466b-a54d-b1330440db98');

Compare two tables in different databases and change one table

I have two databases in the same sql instance. One is backup2 which is a restored backup of my original database.
Database Table
Original.Payments
Backup2.Payments
I have two fields in each that I need to compare:
PaymentsId - guid
IsProcessed - bit
I need to compare the PaymentsId in each and if the payment exists in Backup2 and is marked Processed, I need to mark the Original.Payments.Backup as true.
I have the first part of the query done but I'm not sure how to link it to the Original database:
SELECT [PaymentId]
,[CorporationId]
,[IsProcessed]
FROM [Backup2].[Web].[Payment]
WHERE CorporationId = '2aa2dfw-20d2-4694-8e01-72288a1e8d4'
and IsProcessed = 'true'
This gives me my list of payments but I need to compare those to the original database and I'm not sure how.
Where do I go from here?
Thank you!
you can use update with join syntax
update OP
set IsProcessed = 'true'
FROM [Original].[Payments].[Backup] OP
JOIN [Backup2].[Web].[Payment] BP
on OP.PaymentId = BP.PaymentId
and BP.corporationId = '2aa2dfw-20d2-4694-8e01-72288a1e8d4'
and BP.IsProcessed ='true'
and OP.corporationId = '2aa2dfw-20d2-4694-8e01-72288a1e8d4'
This should be a start
SELECT [p1].[PaymentId]
,[p1].[CorporationId]
,[p1].[IsProcessed]
FROM [Backup2].[Web].[Payment] as [p1]
JOIN [Original].[Web].[Payment] as [p2]
on [p2].[CorporationId] = [p1].[CorporationId]
AND [p2].[PaymentId] = [p1].[PaymentId]
AND [p1].[CorporationId] = '2aa2dfw-20d2-4694-8e01-72288a1e8d4'
and [p1].[IsProcessed =]'true'

Update columns based on subquery containing "select unnest" clause

I am attempting to update a boolean column in one table based upon the values in a second.
UPDATE channels
SET contains_photos = TRUE
WHERE id IN (SELECT unnest(ancestors)
FROM channel_tree WHERE id = 11329);
The channel_tree.ancestors column contains an array of channel IDs. The above is failing with the following error:
ERROR: cannot TRUNCATE "channel_tree" because it is being used by active queries in this session
The overriding goal is to set the contains_photos column to true for all ancestors of a given channel. Any one know how best to alleviate this error, or even an alternative solution?
No idea why your error says TRUNCATE. It sounds like you have a trigger or rule that is doing a truncate that we can't see.
Here's some alternative ways of doing that same query:
UPDATE channels
SET contains_photos = TRUE
WHERE id = ANY (SELECT ancestors
FROM channel_tree WHERE id = 11329);
Or with a join:
UPDATE channels
SET contains_photos = TRUE
FROM channel_tree
WHERE channels.id = ANY (channel_tree.ancestors)
AND channel_tree.id = 11329;