Update a table based on a condition - sql

I have a column Table1.Tradedate and another column Table2.SettlementDate.
Based on the comparison between these 2, I want to update a column in table 2
IF (Table1.TradeDate <= Table2.SettlementDate)
BEGIN
UPDATE Table2 SET Status='Y'
END
This is what I have tried but I know its wrong, since the table will obviously contain more than 1 records. So, I believe what I should do is
use a join on 2 tables based on some #id to pick a particular record
check the IF condition for that particular record
update the Status column in table2.
I hope my approach is correct but I am writing it incorrectly.
Table1:
SKacc | Name | TradeDate | Othercolumns....
1 | xxx | 01/07/2019 |
2 | xxx | 01/06/2019 |
Table2:
SKAcc | Name | SettlementDate | Status |Other Columns....
1 | xxx | 01/08/2019 | NULL |
2 | xxx | 01/08/2019 | NULL |

Try below
update t2 set Status = 'Y'
from table2 t2
join table1 t1 on t1.id = t2.id
where t1.tradeDate <= t2.settlementDate

Try joining the two tables with the related column and then update the table you want to update with the value. Using inner join in the example but can change depending on the usecase
UPDATE Table2
SET Status = 'Y'
FROM Table2
INNER JOIN Table1 ON Table1.id = Table2.table1_id
WHERE Table1.TradeDate <= Table2.SettlementDate

I would not recommend a JOIN for this purpose. Instead:
update table2
set Status = 'Y'
where exists (select 1
from table1 t1
where t1.id = t2.id and
t1.tradeDate <= t2.settlementDate
);
The reason I recommend this version is because you have not specified that id is unique in table1. In general, you only want to use JOIN in UPDATE when you can guarantee that there is only one matching row.

Related

Take data from two tables and show in one row without duplicates with a where condition

I want to take the data from two tables and output them in one row .
output will have two columns "to" and "from" where the condition is "from" will be having data from second table where type is true and "to" column will have data from second table where type is false . FK_ID in second table is linked to ID on the first table . Please help with the query.
I was trying to do with inner joins and union was not able to make it work . Thanks in advance .
TABLE 1
ID | PATH|
1 | ABC |
2 | EFG |
TABLE 2
ID | FK_ID | NUMBER | TYPE
20 | 1 | 123 | TRUE
21 | 1 | 456 | FALSE
28 | 2 | 888 | FALSE
29 | 2 | 939 | TRUE
OUTPUT SHOULD BE:
ID | PATH | TO | FROM
1 | ABC | 456 | 123
2 | EFG | 888 | 939
Use aggregation with pivoting logic to identify the "to" and "from" components of each path:
SELECT
t1.ID,
t1.PATH,
MAX(CASE WHEN t2.TYPE = 'FALSE' THEN t2.NUMBER END) AS "TO",
MAX(CASE WHEN t2.TYPE = 'TRUE' THEN t2.NUMBER END) AS "FROM"
FROM table1 t1
LEFT JOIN table2 t2
ON t1.ID = t2.FK_ID
GROUP BY
t1.ID,
t1.PATH
ORDER BY
t1.ID;
If performance is an issue, you might find a lateral join to be faster:
SELECT t1.*, t2.*
FROM table1 t1 LEFT JOIN LATERAL
(SELECT SUM(T2.NUMBER) FILTER (WHERE NOT t2.TYPE) as num_to,
SUM(T2.NUMBER) FILTER (WHERE t2.TYPE) as num_from
FROM table2 t2
WHERE t1.ID = t2.FK_ID
) t2
ORDER BY t1.ID;
This avoids the outer GROUP BY and probably the sorting as well (assuming that ID is the primary key).
It also assumes that TYPE is a Postgres boolean type. If not, use string comparisons for the WHERE clauses.

SQL query which checks, for each row having a date range in t1, whether there exists any recorded date in t2 within that date range?

If I have two tables like so:
Table 1
Start | END | More columns ...
------------------------------------------
2019-10-20 | 2019-10-21 |...
Table 2
Log ID | DATE
--------------
1 | 2019-10-20
2 | 2019-10-22
I've tried to use CASE WHEN, Boolean, Exists but I suspect my logic is wrong somewhere.
I want to return a results table which includes all of the columns from Table 1, with an additional column containing a Boolean value of whether a date within the range for that row exists in the second table.
So the result set should then look like:
Start | End | MoreCols | Available
----------------------------------------------
2019-10-20 | 2019-10-21 | … | True
Use exists:
select t1.*,
(case when exists (select 1
from table2 t2
where t2.date between t1.start and t1.end
)
then 'True' else 'False'
end) as available_flag
from table1 t1
If your database supports boolean types, then you can write this as:
select t1.*,
(exists (select 1
from table2 t2
where t2.date between t1.start and t1.end
)
) as available_flag
from table1 t1

What is the correct way from performance perspective to match(replace) every value in every row in temp table using SQL Server 2016 or 2017?

I am wondering what should I use in SQL Server 2016 or 2017 (CTE, LOOP, JOINS, CURSOR, REPLACE, etc) to match (replace) every value in every row in temp table? What is the best solution from performance perspective?
Source Table
|id |id2|
| 1 | 2 |
| 2 | 1 |
| 1 | 1 |
| 2 | 2 |
Mapping Table
|id |newid|
| 1 | 3 |
| 2 | 4 |
Expected result
|id |id2|
| 3 | 4 |
| 4 | 3 |
| 3 | 3 |
| 4 | 4 |
You may join the second table to the first table twice:
WITH cte AS (
SELECT
t1.id AS id_old,
t1.id2 AS id2_old,
t2a.newid AS id_new,
t2b.newid AS id2_new
FROM table1 t1
LEFT JOIN table2 t2a
ON t1.id = t2a.id
LEFT JOIN table2 t2b
ON t1.id2 = t2b.id
)
UPDATE cte
SET
id_old = id_new,
id2_old = id2_new;
Demo
Not sure if you want just a select here, or maybe an update, or an insert into another table. In any case, the core logic I gave above should work for all these cases.
You'd need to apply joins on update query. Something like this:
Update tblA set column1 = 'something', column2 = 'something'
from actualName tblA
inner join MappingTable tblB
on tblA.ID = tblB.ID
this query will compare eachrow with ids and if matched then it will update/replace the value of the column as you desire. :)
Do the self join only
SELECT t1.id2 as id, t2.id2
FROM table1 t
INNER JOIN table2 t1 on t1.id = t.id
INNER JOIN table2 t2 on t2.id = t.id2
This may have best performance from solutions posted here if you have indexes set appropriately:
select (select [newid] from MappingTable where id = [ST].[id]) [id],
(select [newid] from MappingTable where id = [ST].[id2]) [id2]
from SourecTable [ST]

SQL Join and Update query

So I want to update the action column to the value 'Insert' inside Table1, if the ids from Table1 and Table2 match but the UIDs dont.
Right now my query looks like
UPDATE Table1
SET Action = 'Insert'
FROM Table1
JOIN Table2 ON Table1.id = Table2.id
AND Table1.UID <> Table2.UID
This is setting the action to Insert even if the UIDs don't differ, can someone help me and explain why this is behaving this way?
My assumption is you have something like this:
Table1
id | UID | action
1 | 1 | bla
1 | 2 | bleck
1 | 3 | floop
Table2
id | UID | action
1 | 1 | bla
1 | 2 | bleck
1 | 4 | floop
And you hope to update the third row in Table1 because the UID isn't in Table2.
The problem is that the third row in Table2 matches all rows in Table1 on your condition: Table1.id = Table2.id AND Table1.UID <> Table2.UID
Which means that in this case, all rows in Table1 will be updated with Action = 'Insert'
I think you want to use NOT EXISTS():
UPDATE T1
SET Action = 'Insert'
FROM Table1 T1
WHERE NOT EXISTS (SELECT *
FROM Table2 T2
WHERE T1.id = T2.id
AND T1.UID = T2.UID)
Edit, more explanation on why the join fails:
This is a many to many join, meaning that the condition allows multiple rows from Table1 to match multiple rows from Table2
The easiest way to see this in action is to change your update to a select:
SELECT *
FROM Table1 T1
JOIN Table2 T2 on T1.id = T2.id
and T1.UID <> T2.UID
You may expect this to result in:
id | UID | action id | UID | action
1 | 3 | floop 1 | 4 | floop
But really it will result in:
id | UID | action id | UID | action
1 | 1 | bla 1 | 4 | floop
1 | 2 | bleck 1 | 4 | floop
1 | 3 | floop 1 | 4 | floop
This means that when you update you are hitting all the rows for id = 1 in Table1
If you put condition Table1.UID <> Table2.UID into WHERE clause, doesn't it solve your problem?
UPDATE Table1
SET Action = 'Insert'
FROM Table1
JOIN Table2 ON Table1.id = Table2.id
WHERE Table1.UID <> Table2.UID

SQL Delete Rows Based on Another Table

This is probably very easy, but it's Monday morning. I have two tables:
Table1:
Field | Type | Null | Key | Default | Extra
id | int(32) unsigned | NO | PRI | NULL | auto_increment
group | int(32) | NO | | 0 |
Table2:
Field | Type | Null | Key | Default | Extra
group | int(32) | NO | | 0 |
Ignoring other fields...I would like a single SQL DELETE statement that will delete all rows in Table1 for which there exists a Table2.group equal to Table1.group. Thus, if a row of Table1 has group=69, that row should be deleted if and only if there exists a row in Table2 with group=69.
Thank you for any help.
I think this is what you want:
DELETE FROM `table1`
WHERE `group` in (SELECT DISTINCT `group` FROM `table2`)
I think this way is faster:
DELETE FROM t1 USING table1 t1 INNER JOIN table2 t2 ON ( t1.group = t2.group );
The nice solution is just writing the SQL as you say it yourself already:
DELETE FROM Table1
WHERE
EXISTS(SELECT 1 FROM Table2 WHERE Table2.Group = Table1.Group)
Regards,
Arno Brinkman
Something like this
delete from table1 where group in (select group from table2)
Off the top of my head:
delete from Table1 where id in (select id from table1 inner join table2 on Table1.group = Table2.group)
I did this a little differently than other posters -- I think if there is a large number of rows on Table2 this might be better. Can someone please set me straight on that?
you can delete either table rows by using its alias in a simple join query like
delete a from table1 a,table2 b where a.uid=b.id and b.id=57;
here, you might specify either a or b to delete the corresponding table rows