How to update multiple tables with one SQL statement in DB2 - db2

Pseudo-code as follows:
update TABLEA a, TABLEB b
set a.addr = 'aaa',
b.name = 'bbb'
from TABLEA a, TABLEB b
where a.id = b.id and a.id = 1

You can only UPDATE one table. So, you can change your SQL to the following:
UPDATE tableA a
SET a.addr = 'aaa'
WHERE exists
(SELECT b.id
FROM tableB b
WHERE b.id = a.id)

Related

SQL - UPSERT LOOP through SELECT's resultset

I have the following query that is returning two columns of data UserID & ServiceID from tables a & b
SELECT a.UserID, b.ServiceID FROM TableA a
JOIN TableB b
ON b.EventID = a.EventID
WHERE a.EventID = 1892286
AND a.Attendance IN (1,2)
The above query returns the following data set:
UserID ServiceID
1 33
2 44
3 55
I need to UPSERT into table c the following way:
If UserID & ServiceID exist in table c then take current value of column Scheduled from table c and add 1
If UserID & ServiceID do NOT exist in table c then insert record into table c with selected UserID and ServiceID from the above select statement and add 1 into the Scheduled column.
My question is how to do this for every single row that is returned by my select statement to ensure all results are UPSERTED into table c
I'm looking through looping case or if-else statements as possible solutions but any input is appreciated.
My attempt at the above:
IF EXISTS (SELECT sa.UserID as S_UserID, ce.ServiceID as S_ServiceID FROM TableA a
JOIN TableB b
ON b.EventID = a.EventID
WHERE a.EventID = 1892286
AND a.Attendance IN (1,2))
UPDATE TableC c
SET
UserID = S_UserID
ServiceID = S_ServiceID
Scheduled = Scheduled + 1
WHERE UserID = S_UserID
AND ServiceID = S_ServiceID
ELSE
INSERT INTO TableC
(UserID,ServiceID,Scheduled)
VALUES
(S_UserID,S_ServiceID,1)
END
If you are on newer version SQL Server (this question is tagged with sql-server-2016), then you can use the MERGE statement.
Here is a somewhat simplified example based on your post:
--create test tables
CREATE TABLE #a (UserID int);
CREATE TABLE #b (UserID int, ServiceID int);
CREATE TABLE #c (UserID int, ServiceID int, Scheduled int);
--insert some data matching the question
INSERT INTO #a
VALUES(1), (2), (3), (4), (5);
INSERT INTO #b
VALUES (1, 33), (2, 44), (3, 55)
INSERT INTO #c
VALUES(2, 44, 3), (4, 66, 1)
--ensure we have data
SELECT * FROM #a
SELECT * FROM #b
SELECT * FROM #c
--use the MERGE statement
MERGE #c AS tgt
USING(SELECT a.UserID, b.ServiceID FROM #a a JOIN #b b ON a.UserID = b.UserID) src
ON (tgt.UserID = src.UserID AND tgt.ServiceID = src.ServiceID)
WHEN NOT MATCHED THEN
INSERT (UserID, ServiceID, Scheduled)
VALUES(src.UserID, src.ServiceID, 1)
WHEN MATCHED THEN
UPDATE
SET Scheduled += 1;
--check what's been inserted/updated
SELECT * FROM #c
Be aware that MERGE sometimes gave performance implications, so use it with caution. More info about MERGE here.
Hope this helps!
One way to do this is by executing different statements for inserting and updating.
-- INSERT INTO Temporary Table
SELECT sa.UserID,
ce.ServiceID
INTO #tempC
FROM TableA a
JOIN TableB b ON b.EventID = a.EventID
WHERE a.EventID = 1892286
AND a.Attendance IN (1,2)
-- UPDATE Existing ROWS
UPDATE c
SET c.Scheduled = c.Scheduled + 1
FROM #tempC c
INNER JOIN TableC d
ON c.UserID = d.UserID
AND c.ServiceID = d.ServiceID
-- INSERT new rows
INSERT INTO TableC (UserID, ServiceID,Scheduled)
SELECT c.UserID, c.ServiceID, 1
FROM #tempC c
LEFT JOIN TableC d
ON c.UserID = d.UserID
AND c.ServiceID = d.ServiceID
WHERE d.UserID IS NULL
-- DROP temporary table
DROP TABLE #tempC
A loop is not efficient
ca and ce are not valid alias so I had to guess the valid alias
Start with a backup in case you do it wrong.
update c
set c.serviceID = c.serviceID + 1
FROM TableA a
JOIN TableB b
ON b.EventID = a.EventID
and a.EventID = 1892286
AND a.Attendance IN (1,2)
join TableC c
on c.UserID = a.UserID
and c.ServiceID = b.ServiceID;
INSERT INTO TableC (UserID, ServiceID, Scheduled)
SELECT a.UserID, b.ServiceID, 1
FROM TableA a
JOIN TableB b
ON b.EventID = a.EventID
and a.EventID = 1892286
AND a.Attendance IN (1,2)
where not exists (select 1
from TableC c
where c.UserID = a.UserID
and c.ServiceID = b.ServiceID
);

Postgresql query between 2 tables

There are 3 fields in TABLE_A (id1,id2,value), 2 fields in TABLE_B(id,name). I want to get the name instead of id1/id2 according to id=id1/id=di2
select id1,id2,value from TABLE_A;
select name from TABLE_B where id=id1;
select name from TABLE_B where id=id2;
How to combine these three statements into one, and return the results like following:
name(id1) | name(id2) | value
Try this:
select c.name, b.name, a.value from TABLE_A a, TABLE_B b, TABLE_B c
where b.id = a.id1 and c.id = a.id2

T-SQL: how to sort table rows based on 2 columns

I'm quite stuck with this problem for sometime now..
How do I sort column A depending on the contents of Column B?
I have this sample:
ID count columnA ColumnB
-----------------------------------
12 1 A B
13 2 C D
14 3 B C
I want to sort it like this:
ID count ColumnA ColumnB
-----------------------------------
12 1 A B
14 3 B C
13 2 C D
so I need to sort the rows if the previous row of ColumnB = the next row of ColumnA
I'm thinking a loop? but can't quite imagine how it will work...
I was thinking it will go like this (maybe)
SELECT
a.ID, a.ColumnA, a.ColumnB
FROM
TableA WITH a (NOLOCK)
LEFT JOIN
TableA b WITH (NOLOCK) ON a.ID = b.ID AND a.counts = b.counts
WHERE
a.columnB = b.ColumnA
the above code isn't working though and I was thinking more on the lines of...
DECLARE #counts int = 1
DECLARE #done int = 0
--WHILE #done = 0
BEGIN
SELECT
a.ID, a.ColumnA, a.ColumnB
FROM
TableA WITH a (NOLOCK)
LEFT JOIN
TableA b WITH (NOLOCK) ON a.ID = b.ID AND a.counts = #counts
WHERE
a.columnB = b.ColumnA
set #count = #count +1
END
If this was a C code, would be easier for me but T-SQL's syntax is making it a bit harder for a noobie like me.
Any help is greatly appreciated!
Edit: sample code
drop table tablea
create table TableA(
id int,
colA varchar(10),
colb varchar(10),
counts int
)
insert INTO TableA
(id, cola, colb, counts)
select 12, 'Bad', 'Cat', 3
insert INTO TableA
(id, cola, colb, counts)
select 13, 'Apple', 'Bad', 1
insert INTO TableA
(id, cola, colb, counts)
select 14, 'Cat', 'Dog', 2
select * FROM TableA
SELECT a.ID, a.ColA, a.ColB
FROM TableA a WITH (NOLOCK)
LEFT JOIN TableA b WITH (NOLOCK)
ON a.ID = b.ID
Where a.colB = b.ColA
ORDER BY a.ColA ASC
you just need to add ORDER BY clause
-- SELECT a.ID, a.ColumnA, a.ColumnB
-- FROM TableA WITH a (NOLOCK)
-- LEFT JOIN TableA b WITH (NOLOCK)
-- ON a.ID = b.ID
-- and a.counts = b.counts
-- Where a.columnB = b.ColumnA
ORDER BY a.ColumnA ASC
This is all you need. Sometimes you have to think simple
select * from table A
order by columnA asc

Transfer existing data after database model changes (PostgreSQL)

I'm trying to remove an association table from my database. It contains two columns (a_id and b_id) referencing the tables a and b.
This table is unnecessary because in fact it's an OneToMany relation. So I added column a_id in table b.
My problem: How can I transfer the existing entrys from assoc_a_b to b.a_id?
SELECT DISTINCT b.id, a.id FROM table_a AS a
JOIN assoc_a_b AS assoc ON a.id = assoc.a_id
JOIN table_b AS b ON b.id = assoc.b_id;
This select statement works. Can it be combined with an UPDATE statement? The UPDATE statement would look someway like:
UPDATE b SET a_id = a.id WHERE id = b.id;
using a.id and b.id from the select statement above.
update b set a_id = (SELECT assoc_a_b.a_id from assoc_a_b where assoc_a_b.b_id = b.id)

sql server 2005/2008 conditional join

Is there such thing like conditional join:
SELECT *
FROM TABLE1 A
IF (a=='TABLE2') THEN INNER JOIN TABLE2 B ON A.item_id=B.id
ELSE IF (a=='TABLE3') THEN INNER JOIN TABLE3 C ON A.item_id=C.id
While a is a field in TABLE1.
I like to use this in stored procedures without using dynamic sql (without writing query as string and EXEC(#query)).
EDIT: I can't write:
IF (a=='TABLE2) THEN queryA
ELSE IF (a=='TABLE3') THEN queryB
Because a is a field of TABLE1.
EDIT: Modified answer based on comment below:
You could try to get clever with some left joins. This will return more columns, so you'd probably want to be more discriminating than just SELECT *.
SELECT *
FROM TABLE1 A
LEFT JOIN TABLE2 B
ON A.item_id = B.id
AND A.a = 'TABLE2'
LEFT JOIN TABLE3 C
ON A.item_id = C.id
AND A.a = 'TABLE3'
WHERE (B.id IS NOT NULL AND A.a = 'TABLE2')
OR (C.id IS NOT NULL AND A.a = 'TABLE3')
Updated the query as requried:
SELECT * FROM
(
SELECT *
FROM TABLE1 A INNER JOIN TABLE2 B
ON A.a='TABLE2' --This will eleminate the table rows if the value of A.a is not 'TABLE2'
AND A.item_id=B.id) A,
(SELECT * FROM
INNER JOIN TABLE3 C
ON A.a='TABLE3' --This will eleminate the table rows if the value of A.a is not 'TABLE3'
AND A.item_id=C.id
) B
) a