modify value on a table with some conditions - sql

I need some help with mssql. I dont know anything from mssql query, but I know some programing.
I have 2 tables, TableA and TableB each one has 2 columns
ColumnA1, ColumnA2, ColumnB1 and ColumnB2
Something like this
create table DB.dbo.TableA
(ColumnA1 varchar(10),
ColumnA2 int)
create table DB.dbo.TableB
(ColumnB1 varchar(10),
ColumnB2 int)
And I need to check if exist a row in TableA where ColumnA2>0
if so, then,
IF any of those possible rows also exists in ColumnB1,
update ColumnB2=ColumnB2+ColumnA2 and set ColumnA2=0
ELSE
insert a new row in TableB with ColumnB1=ColumnA1 and ColumnB2=ColumnA1 and set ColumnA2=0
I don't even know where to start, I tryed to explain it the best way I could.
EDIT:
Before the script
TableA:
ColumnA1 ColumnA2
John 0
Sam 1
Mark 1
TableB:
ColumnB1 ColumnB2
Sam 5
After the script should be something like this:
TableA:
ColumnA1 ColumnA2
John 0
Sam 0
Mark 0
TableB:
ColumnB1 ColumnB2
Sam 6
Mark 1

You should use the MERGE syntax
merge TableB
using
(select * from tablea where ColumnA2>0) source
ON source.ColumnA1 = tableb.ColumnB1
when matched then
update
set tableb.ColumnB2 = tableb.ColumnB2 + source.ColumnA2
when not matched by target Then
insert(ColumnB1,ColumnB2)
values (source.ColumnA1,source.ColumnA2)

I couldn't get your requirement properly but the below code using Merge will atleast help you in the right direction .
MERGE TableB B
USING TableA A
ON A.ColumnA1 = B.ColumnB1 //The columns which related to both the tables
WHEN MATCHED AND
A.ColumnA2>0 THEN
UPDATE
SET B.ColumnB2 = B.ColumnB2 + A.ColumnA2
when not matched by target Then
Insert(ColumnB1,ColumnB2)
values (A.ColumnA1,A.ColumnB2)
Output A.ColumnA1 into #t;
Update TableA
Set ColumnA2=0
WHERE ColumnA1 in (SELECT ColumnA1
FROM #t);

Related

Compare data between two tables and update one table data

I have two tables and i need to compare data and update one table records. Please let me know how this can be done, i am trying to not use merge. This is the scenario
Proj1 Table
This is the first table where data needs to be synchronized
ID Text
1 R1
2 R2
3 R3
Proj2 Table
This is the table where data updates are taking place
ID Text Active
3 R1 1
4 R3 1
5 R4 1
After a compare is done on Text field between both these tables result should be similar to below. We are syncing data in Proj2 to similar to Proj1.
ID Text Active
3 R1 1 (Ignore as it exists in both tables)
4 R3 1 (Ignore as it exists in both tables)
5 R4 0 (Update to inactive as it does not exist Proj1 table)
6 R2 1 (Insert as it does not exist in Proj2 table)
If you really can't use MERGE, you can simply split it into an update and an insert query :
INSERT INTO #Proj2(Text, Active)
SELECT Text,1 FROM #Proj1 p1
WHERE NOT EXISTS(
SELECT *
FROM #Proj2 p2
WHERE p2.Text = p1.Text
);
UPDATE
p2
SET
p2.Active = CASE WHEN p1.id is null THEN 0 ELSE 1 END
FROM
#Proj2 p2
LEFT JOIN
#Proj1 p1
ON
p2.Text = p1.Text;
This assumes that your ID is an auto-increment.
Thsi is pretty much like Zak's new answer, but with the 2 update queries merged.
merge [Proj2Table] target
using ( select [id], [text] from [Proj1Table] ) source ([id], [text] )
on target.[id] = source.[id]
when not matched by source
then update
set target.[Active] = 0
when not matched by target
then insert
([id], [text] )
values( source.[id], source.[text] )
-- update records in table 2 that cannot be found in table 1
update P2
set P2.[Active] = 0
from [Proj2Table] as P2
left join [Proj1TAble] as P1 on P1.[text] = P2.[text]
where P1.[id] is null;
-- update records in table 2 that can be found in table 1
update P2
set P2.[Active] = 1
from [Proj2Table] as P2
join [Proj1TAble] as P1 on P1.[text] = P2.[text];
-- insert missing records from table 1 into table 2 with active bit set
insert into [Proj2Table] ([id] , [text] , [active] )
select [id] , [text] , [active] = 1
from [Proj1Table] as P1
where not exists (select 1 from [Proj2Table] as P2 where P2.[text] = P1.[text])
;
Not sure if [id] column should match or is a pk/identity/sequence
Another approach would be to use a cursor, if you really don't want to use MERGE
-declare a cursor on the first table and scroll the row, then for each row selct the corresponding row in the second table and ac accordingly, if found/not found...
not the best performance-related suggestion though...

need clarification on where not exists clause

I am trying to insert only those records into #AltDealNames table for which DealName exists in #DistDeal table but not in #AltDealNames table. For this I am trying not exists clause. But it is not working as expected. Query is simply dumping records into #AltDealNames table.
insert into #AltDealNames
select d.DealName, d.ManagerScrubbed, d.BbgDealName, t.TrancheName, t.StreetCusip, t.ISIN, t.BbgTrancheName
from metric..Deal d join metric..Tranche t on d.DealName = t.DealName
where not exists(select 1 from #DistDeal dd join #AltDealNames ad on ad.DealName = dd.DealName)
Please help me to know if I am doing something wrong while building query.
If I understand correctly, you want an exists clause for #DistDeal and a not exists for #AltDealNames:
insert into #AltDealNames
select d.DealName, d.ManagerScrubbed, d.BbgDealName, t.TrancheName,
t.StreetCusip, t.ISIN, t.BbgTrancheName
from metric..Deal d join
metric..Tranche t
on d.DealName = t.DealName
where exists (select 1 from #DistDeal dd where dd.DealName = d.DealName) and
not exists (select 1 from #AltDealNames ad on ad.DealName = dd.DealName);
Note: when using insert, you should always include the list of column names.
Depending on how the optimizer sets up the actual physical query, the "where not exists" clause might run first, before anything is inserted by this query. Ie., it would only filter on values in #AltDealNames that were there from a previous query.
If you're trying to avoid inserting DealName values that are in #DistDeal, then maybe you want:
insert into #AltDealNames
select d.DealName, d.ManagerScrubbed, d.BbgDealName, t.TrancheName,
t.StreetCusip, t.ISIN, t.BbgTrancheName
from metric..Deal d
join metric..Tranche t on d.DealName = t.DealName
where not exists(select 1 from #DistDeal dd
where d.DealName = dd.DealName) -- Changed line

Update table a from table b where (conditions)

Evening all,
Actually, it's night. About 11pm. My brain is shutting down and I need a bit of help so I can finish and go home :)
I have two tables - table a and table b.
I need to update a field in table a with the value from a field in table b when two other fields match. The tables don't have a unique id for each record :(
Basically, I want to do this:
update a
set importantField =
(select b.importantfield
from b
where a.matchfield = b.matchfield
and a.matchfield2 = b.matchfield2
)
where a.matchfield = b.matchfield
and a.matchfield2 = b.matchfield2
Or at least... I think that's what I want to do...
Can someone help me out, please?
You can do this via a join in the update:
Update a
Set a.importantField = b.importantField
From a Join b
On a.matchfield = b.matchfield
And a.matchfield2 = b.matchfield2
Use:
UPDATE TABLE_A
SET importantField = (SELECT b.importantfield
FROM TABLE_B b
WHERE b.matchfield = matchfield
AND b.matchfield2 = matchfield2)
SQL Server doesn't support table aliases on the table being updated, but the above is a correlated query - those fields without the table alias b attached will serve values from TABLE_A because it doesn't have an alias.
The only issue beyond that is if there are multiple b.importantfield values for records with the matching records to TABLE_A. Use:
UPDATE TABLE_A
SET importantField = (SELECT TOP 1
b.importantfield
FROM TABLE_B b
WHERE b.matchfield = matchfield
AND b.matchfield2 = matchfield2)
..but you should use an ORDER BY as well or you'll get any random b.importantfield value.

UPDATE row when matching row exists in another table

I need to update a field on a table to be true only if a matching row exists in another table, for all the rows where the column is currently null in the main table.
This is a description of what I want to achieve:
UPDATE [LenqReloaded].[dbo].[Enquiry] A
SET [ResponseLetterSent] = 1
WHERE [ResponseLetterSent] IS NULL
AND EXISTS
(
SELECT * FROM [LenqReloaded].[dbo].[Attachment] B
WHERE A.[EnquiryID] = B.[EnquiryID]
)
This isn't syntactically correct.
I can't code it via an IF EXISTS... statement because I don't have the [EnquiryID] without reading the data from the table.
How should I format my UPDATE statement?
You weren't far off...
UPDATE A
SET A.[ResponseLetterSent] = 1
FROM [LenqReloaded].[dbo].[Enquiry] A
WHERE A.[ResponseLetterSent] IS NULL
AND EXISTS ( SELECT * FROM [LenqReloaded].[dbo].[Attachment] B WHERE A.[EnquiryID] = B.[EnquiryID] )
You need to use a join in your update:
UPDATE [LenqReloaded].[dbo].[Enquiry] SET [ResponseLetterSent] = 1
FROM [LenqReloaded].[dbo].[Enquiry] A
join [LenqReloaded].[dbo].[Attachment] B on A.[EnquiryID] = B.[EnquiryID]
WHERE A.[ResponseLetterSent] IS NULL
This seems counterintuitive, but you need to establish a table alias in a From clause but use that alias in the Update Clause...
Update E Set
ResponseLetterSent = 1
From LenqReloaded.dbo.Enquiry E
Where ResponseLetterSent Is Null
And Exists (Select * From LenqReloaded.dbo.Attachment
Where EnquiryID = E.EnquiryID)
The thing you are missing is the 'from' clause, which is a t-sql extension - it is the only way to assign an alias to the updated table
update [lenqreloaded].[dbo].[enquiry]
set [responselettersent] = 1
from [lenqreloaded].[dbo].[enquiry] a
where [responselettersent] is null
and exists (
select *
from [lenqreloaded].[dbo].[attachment] b
where a.[enquiryid] = b.[enquiryid]
)

update each row in a procedure

I have the following data in a table TABLE1
DOCUMENT ------ FIELD1
12345
23456
34567
45678
98765
i have the following data in a view VIEW1
DOCUMENT ---- BUS
12345 ------------ 5
23456 ------------ 6
34567 ------------ 8
45678 ------------ 12
98765 ------------ 14
What i would like to do is update each row
if (table1.document = view1.document)
then
table1.field1 = view1.bus
Any insight will help.
Thank you.
That can be done using plain SQL, no procedures required:
UPDATE table1 SET field1 = (SELECT bus FROM view1 WHERE table1.document = view1.document)
Or, if your database allows it:
UPDATE (select table1.field1, view1.bus FROM table1 JOIN view1 ON table1.document = view1.document) SET table1.field1 = view1.bus
As Dan said, but in MS SQL Server I find this styling easier to read:
UPDATE U
SET U.field1 = V.bus
FROM table1 AS U
JOIN view1 AS V
ON V.document = U.document
Note that if VIEW1 could have multiple rows for a given TABLE1 row [DOCUMENT] value then the [BUS] value choosen to update TABLE1 will be random, within the matching set. (If this is the case the query could be modified to choose MAX / MIN / etc.)
I would refine this query to NOT update any rows that already matched the BUS value, which will make it faster if it is rerun and thus some values already exist in TABLE1
UPDATE U
SET U.field1 = V.bus
FROM table1 AS U
JOIN view1 AS V
ON V.document = U.document
WHERE U.field1 = V.bus
OR (U.field1 IS NOT NULL AND V.bus IS NULL)
OR (U.field1 IS NULL AND V.bus IS NOT NULL)
you can leave out the NULL / NOT NULL tests if the field is defined as not allowing NULLs.