SQL Update related data when new table and data is added [duplicate] - sql

I have to update a field with a value which is returned by a join of 3 tables.
Example:
select
im.itemid
,im.sku as iSku
,gm.SKU as GSKU
,mm.ManufacturerId as ManuId
,mm.ManufacturerName
,im.mf_item_number
,mm.ManufacturerID
from
item_master im, group_master gm, Manufacturer_Master mm
where
im.mf_item_number like 'STA%'
and im.sku=gm.sku
and gm.ManufacturerID = mm.ManufacturerID
and gm.manufacturerID=34
I want to update the mf_item_number field values of table item_master with some other value which is joined in the above condition.
How can I do this in MS SQL Server?

UPDATE im
SET mf_item_number = gm.SKU --etc
FROM item_master im
JOIN group_master gm
ON im.sku = gm.sku
JOIN Manufacturer_Master mm
ON gm.ManufacturerID = mm.ManufacturerID
WHERE im.mf_item_number like 'STA%' AND
gm.manufacturerID = 34
To make it clear... The UPDATE clause can refer to an table alias specified in the FROM clause. So im in this case is valid
Generic example
UPDATE A
SET foo = B.bar
FROM TableA A
JOIN TableB B
ON A.col1 = B.colx
WHERE ...

Adapting this to MySQL -- there is no FROM clause in UPDATE, but this works:
UPDATE
item_master im
JOIN
group_master gm ON im.sku=gm.sku
JOIN
Manufacturer_Master mm ON gm.ManufacturerID=mm.ManufacturerID
SET
im.mf_item_number = gm.SKU --etc
WHERE
im.mf_item_number like 'STA%'
AND
gm.manufacturerID=34

One of the easiest way is to use a common table expression (since you're already on SQL 2005):
with cte as (
select
im.itemid
,im.sku as iSku
,gm.SKU as GSKU
,mm.ManufacturerId as ManuId
,mm.ManufacturerName
,im.mf_item_number
,mm.ManufacturerID
, <your other field>
from
item_master im, group_master gm, Manufacturer_Master mm
where
im.mf_item_number like 'STA%'
and im.sku=gm.sku
and gm.ManufacturerID = mm.ManufacturerID
and gm.manufacturerID=34)
update cte set mf_item_number = <your other field>
The query execution engine will figure out on its own how to update the record.

Did not use your sql above but here is an example of updating a table based on a join statement.
UPDATE p
SET p.category = c.category
FROM products p
INNER JOIN prodductcatagories pg
ON p.productid = pg.productid
INNER JOIN categories c
ON pg.categoryid = c.cateogryid
WHERE c.categories LIKE 'whole%'

You can specify additional tables used in determining how and what to update with the "FROM " clause in the UPDATE statement, like this:
update item_master
set mf_item_number = (some value)
from
group_master as gm
join Manufacturar_Master as mm ON ........
where
.... (your conditions here)
In the WHERE clause, you need to provide the conditions and join operations to bind these tables together.
Marc

MySQL: In general, make necessary changes par your requirement:
UPDATE
shopping_cart sc
LEFT JOIN
package pc ON sc. package_id = pc.id
SET
sc. amount = pc.amount

It is very simple to update using join query in SQL .You can do it without using FROM clause. Here is an example :
UPDATE customer_table c
JOIN
employee_table e
ON c.city_id = e.city_id
JOIN
anyother_ table a
ON a.someID = e.someID
SET c.active = "Yes"
WHERE c.city = "New york";

You can use the following query:
UPDATE im
SET mf_item_number = (some value)
FROM item_master im
JOIN group_master gm
ON im.sku = gm.sku
JOIN Manufacturer_Master mm
ON gm.ManufacturerID = mm.ManufacturerID
WHERE im.mf_item_number like 'STA%' AND
gm.manufacturerID = 34 `sql`

Try like this...
Update t1.Column1 = value
from tbltemp as t1
inner join tblUser as t2 on t2.ID = t1.UserID
where t1.[column1]=value and t2.[Column1] = value;

If you are using SQL Server you can update one table from other table without specifying a join and simply link the two tables from the where clause. This makes a much simpler SQL query:
UPDATE Table1
SET Table1.col1 = Table2.col1,
Table1.col2 = Table2.col2
FROM
Table2
WHERE
Table1.id = Table2.id

You can update with MERGE Command with much more control over MATCHED and NOT MATCHED:(I slightly changed the source code to demonstrate my point)
USE tempdb;
GO
IF(OBJECT_ID('target') > 0)DROP TABLE dbo.target
IF(OBJECT_ID('source') > 0)DROP TABLE dbo.source
CREATE TABLE dbo.Target
(
EmployeeID INT ,
EmployeeName VARCHAR(100) ,
CONSTRAINT Target_PK PRIMARY KEY ( EmployeeID )
);
CREATE TABLE dbo.Source
(
EmployeeID INT ,
EmployeeName VARCHAR(100) ,
CONSTRAINT Source_PK PRIMARY KEY ( EmployeeID )
);
GO
INSERT dbo.Target
( EmployeeID, EmployeeName )
VALUES ( 100, 'Mary' );
INSERT dbo.Target
( EmployeeID, EmployeeName )
VALUES ( 101, 'Sara' );
INSERT dbo.Target
( EmployeeID, EmployeeName )
VALUES ( 102, 'Stefano' );
GO
INSERT dbo.Source
( EmployeeID, EmployeeName )
VALUES ( 100, 'Bob' );
INSERT dbo.Source
( EmployeeID, EmployeeName )
VALUES ( 104, 'Steve' );
GO
SELECT * FROM dbo.Source
SELECT * FROM dbo.Target
MERGE Target AS T
USING Source AS S
ON ( T.EmployeeID = S.EmployeeID )
WHEN MATCHED THEN
UPDATE SET T.EmployeeName = S.EmployeeName + '[Updated]';
GO
SELECT '-------After Merge----------'
SELECT * FROM dbo.Source
SELECT * FROM dbo.Target

Let me just add a warning to all the existing answers:
When using the SELECT ... FROM syntax, you should keep in mind that it is proprietary syntax for T-SQL and is non-deterministic. The worst part is, that you get no warning or error, it just executes smoothly.
Full explanation with example is in the documentation:
Use caution when specifying the FROM clause to provide the criteria for the update operation. The results of an UPDATE statement are undefined if the statement includes a FROM clause that is not specified in such a way that only one value is available for each column occurrence that is updated, that is if the UPDATE statement is not deterministic.

I've been trying to do things like this forever and it just occurred to me to try using the following syntax (using tuples)
update dstTable T
set (T.field1, T.field2, T.field3) =
(select S.value1, S.value2, S.value3
from srcTable S
where S.key = T.Key);
And surprisingly it worked. I'm using Oracle (12c I think). Is this standard SQL or Oracle specific?
NB: In my example I'm updating the entire table (filling new columns). The update has no where clause so all rows will be updated. Your fields will be set to NULL when the subquery doesn't return a row. (and it must not return more than one row).

Related

UPDATE TABLE 01 FROM TABLE O2 WITH SAME KEY [duplicate]

I have to update a field with a value which is returned by a join of 3 tables.
Example:
select
im.itemid
,im.sku as iSku
,gm.SKU as GSKU
,mm.ManufacturerId as ManuId
,mm.ManufacturerName
,im.mf_item_number
,mm.ManufacturerID
from
item_master im, group_master gm, Manufacturer_Master mm
where
im.mf_item_number like 'STA%'
and im.sku=gm.sku
and gm.ManufacturerID = mm.ManufacturerID
and gm.manufacturerID=34
I want to update the mf_item_number field values of table item_master with some other value which is joined in the above condition.
How can I do this in MS SQL Server?
UPDATE im
SET mf_item_number = gm.SKU --etc
FROM item_master im
JOIN group_master gm
ON im.sku = gm.sku
JOIN Manufacturer_Master mm
ON gm.ManufacturerID = mm.ManufacturerID
WHERE im.mf_item_number like 'STA%' AND
gm.manufacturerID = 34
To make it clear... The UPDATE clause can refer to an table alias specified in the FROM clause. So im in this case is valid
Generic example
UPDATE A
SET foo = B.bar
FROM TableA A
JOIN TableB B
ON A.col1 = B.colx
WHERE ...
Adapting this to MySQL -- there is no FROM clause in UPDATE, but this works:
UPDATE
item_master im
JOIN
group_master gm ON im.sku=gm.sku
JOIN
Manufacturer_Master mm ON gm.ManufacturerID=mm.ManufacturerID
SET
im.mf_item_number = gm.SKU --etc
WHERE
im.mf_item_number like 'STA%'
AND
gm.manufacturerID=34
One of the easiest way is to use a common table expression (since you're already on SQL 2005):
with cte as (
select
im.itemid
,im.sku as iSku
,gm.SKU as GSKU
,mm.ManufacturerId as ManuId
,mm.ManufacturerName
,im.mf_item_number
,mm.ManufacturerID
, <your other field>
from
item_master im, group_master gm, Manufacturer_Master mm
where
im.mf_item_number like 'STA%'
and im.sku=gm.sku
and gm.ManufacturerID = mm.ManufacturerID
and gm.manufacturerID=34)
update cte set mf_item_number = <your other field>
The query execution engine will figure out on its own how to update the record.
Did not use your sql above but here is an example of updating a table based on a join statement.
UPDATE p
SET p.category = c.category
FROM products p
INNER JOIN prodductcatagories pg
ON p.productid = pg.productid
INNER JOIN categories c
ON pg.categoryid = c.cateogryid
WHERE c.categories LIKE 'whole%'
You can specify additional tables used in determining how and what to update with the "FROM " clause in the UPDATE statement, like this:
update item_master
set mf_item_number = (some value)
from
group_master as gm
join Manufacturar_Master as mm ON ........
where
.... (your conditions here)
In the WHERE clause, you need to provide the conditions and join operations to bind these tables together.
Marc
MySQL: In general, make necessary changes par your requirement:
UPDATE
shopping_cart sc
LEFT JOIN
package pc ON sc. package_id = pc.id
SET
sc. amount = pc.amount
It is very simple to update using join query in SQL .You can do it without using FROM clause. Here is an example :
UPDATE customer_table c
JOIN
employee_table e
ON c.city_id = e.city_id
JOIN
anyother_ table a
ON a.someID = e.someID
SET c.active = "Yes"
WHERE c.city = "New york";
You can use the following query:
UPDATE im
SET mf_item_number = (some value)
FROM item_master im
JOIN group_master gm
ON im.sku = gm.sku
JOIN Manufacturer_Master mm
ON gm.ManufacturerID = mm.ManufacturerID
WHERE im.mf_item_number like 'STA%' AND
gm.manufacturerID = 34 `sql`
Try like this...
Update t1.Column1 = value
from tbltemp as t1
inner join tblUser as t2 on t2.ID = t1.UserID
where t1.[column1]=value and t2.[Column1] = value;
If you are using SQL Server you can update one table from other table without specifying a join and simply link the two tables from the where clause. This makes a much simpler SQL query:
UPDATE Table1
SET Table1.col1 = Table2.col1,
Table1.col2 = Table2.col2
FROM
Table2
WHERE
Table1.id = Table2.id
You can update with MERGE Command with much more control over MATCHED and NOT MATCHED:(I slightly changed the source code to demonstrate my point)
USE tempdb;
GO
IF(OBJECT_ID('target') > 0)DROP TABLE dbo.target
IF(OBJECT_ID('source') > 0)DROP TABLE dbo.source
CREATE TABLE dbo.Target
(
EmployeeID INT ,
EmployeeName VARCHAR(100) ,
CONSTRAINT Target_PK PRIMARY KEY ( EmployeeID )
);
CREATE TABLE dbo.Source
(
EmployeeID INT ,
EmployeeName VARCHAR(100) ,
CONSTRAINT Source_PK PRIMARY KEY ( EmployeeID )
);
GO
INSERT dbo.Target
( EmployeeID, EmployeeName )
VALUES ( 100, 'Mary' );
INSERT dbo.Target
( EmployeeID, EmployeeName )
VALUES ( 101, 'Sara' );
INSERT dbo.Target
( EmployeeID, EmployeeName )
VALUES ( 102, 'Stefano' );
GO
INSERT dbo.Source
( EmployeeID, EmployeeName )
VALUES ( 100, 'Bob' );
INSERT dbo.Source
( EmployeeID, EmployeeName )
VALUES ( 104, 'Steve' );
GO
SELECT * FROM dbo.Source
SELECT * FROM dbo.Target
MERGE Target AS T
USING Source AS S
ON ( T.EmployeeID = S.EmployeeID )
WHEN MATCHED THEN
UPDATE SET T.EmployeeName = S.EmployeeName + '[Updated]';
GO
SELECT '-------After Merge----------'
SELECT * FROM dbo.Source
SELECT * FROM dbo.Target
Let me just add a warning to all the existing answers:
When using the SELECT ... FROM syntax, you should keep in mind that it is proprietary syntax for T-SQL and is non-deterministic. The worst part is, that you get no warning or error, it just executes smoothly.
Full explanation with example is in the documentation:
Use caution when specifying the FROM clause to provide the criteria for the update operation. The results of an UPDATE statement are undefined if the statement includes a FROM clause that is not specified in such a way that only one value is available for each column occurrence that is updated, that is if the UPDATE statement is not deterministic.
I've been trying to do things like this forever and it just occurred to me to try using the following syntax (using tuples)
update dstTable T
set (T.field1, T.field2, T.field3) =
(select S.value1, S.value2, S.value3
from srcTable S
where S.key = T.Key);
And surprisingly it worked. I'm using Oracle (12c I think). Is this standard SQL or Oracle specific?
NB: In my example I'm updating the entire table (filling new columns). The update has no where clause so all rows will be updated. Your fields will be set to NULL when the subquery doesn't return a row. (and it must not return more than one row).

need to replace subquery with JOIN

I need to use join in below instead of Subquery.
can anybody help me to rewrite this with JOIN.
update Table1
set status = 'Edited'
where val_74 ='1' and status ='Valid'
and val_35 is not null
and (val_35,network_id) in
(select val_35,network_id from
Table2 where val_35 is not null
and status='Correct_1');
update Table1 b SET (Val_12,Val_13,Val_14)=
(select Val_12,Val_13,Val_14 from
(select Val_35,network_id, Val_12, Val_13, Val_14
from Table2
where Val_34 is not null
and (REGEXP_LIKE(Val_13,'^[0-9]+$'))
and (Val_14 is null or (REGEXP_LIKE(Val_14,'^[0-9]+$')))
group by Val_35,network_id,Val_12,Val_13,Val_14
)
where Val_35 = b.Val_35 and network_id = b.network_id and rownum=1
)
where status = 'PCStep2' and (regexp_like(Val_13,'[MSS]+') or regexp_like(Val_14,'[MSS]+'));
I tried a lot with my less Knowledge In SQL JOINs. but getting multiple erros.
can anybody help me with the queries at the earliest.
Hearty thanks in advance
Actually you can not mix a update statement with a join statement. An update statement always expects exactly one table definition after the update command.
-- ORA-00971: missing SET keyword
update orders o, customers c
set o.order_value = c.account_value
where o.cust_id = c.cust_id
-- works fine
update orders o
set o.order_value = (select c.account_value
from customers c
where c.id = o.cust_id)

Update Value in Sql

Good Day Guys. Im creating sql syntax which subtract the current value of ContractQty to TotalAmountQty.
The code Below subtract ContractQty and TotalAmountQty in Temporary Table. My Question is how can I update the value of ContractQty to my Table Retail. XDeal ColumnName ContractQty where DocNumber. getting the data from Temporary Table? The value in the screen shoot need to get and update my column ContractQty in Retail.XDeal Thanks Regards
WITH A AS (SELECT A.DocNumber,SUM(B.Qty) AS TotalAmountQty
FROM Retail.XDeal A
INNER JOIN Retail.XDealDetail B
ON A.DocNumber = B.DocNumber
GROUP BY A.DocNumber)
SELECT SUM(A.ContractQty-B.TotalAmountQty) as ContractQty FROM Retail.XDeal A
INNER JOIN A B
ON A.DocNumber = B.DocNumber
You can do an update with a join in SQL Server. This is the syntax:
WITH A AS (
SELECT xd.DocNumber, SUM(xdd.Qty) AS TotalAmountQty
FROM Retail.XDeal xd INNER JOIN
Retail.XDealDetail xdd
ON xd.DocNumber = xdd.DocNumber
GROUP BY xd.DocNumber
)
UPDATE xd
SET ContractQty = A.TotalAmountQty
FROM Retail.XDetail xd JOIN
A
ON xd.DocNumber = A.DocNumber;
The join for A is unnecessary, so this is a simpler version:
WITH A AS (
SELECT xdd.DocNumber, SUM(xdd.Qty) AS TotalAmountQty
FROM Retail.XDealDetail xdd
GROUP BY xdd.DocNumber
)
UPDATE xd
SET ContractQty = A.TotalAmountQty
FROM Retail.XDetail xd JOIN
A
ON xd.DocNumber = A.DocNumber;
Personally, I would make the CTE a subquery, but that is just a matter of preference.
I think I understand what you're trying to do; this should work:
SELECT DocNumber, SUM(Qty) AS TotalAmountQty
INTO #temp
FROM Retail.XDealDetail
GROUP BY DocNumber
UPDATE Retail.XDeal
SET ContractQty = A.ContractQty - B.TotalAmountQty
FROM Retail.XDeal A
JOIN #temp B ON A.DocNumber = B.DocNumber;
DROP TABLE #temp;
You don't mention version of sql-server, but recent versions support MERGE:
MERGE INTO Retail.XDeal xd2
USING (
SELECT xd.DocNumber, SUM(xdd.Qty) AS TotalAmountQty
FROM Retail.XDeal xd
JOIN Retail.XDealDetail xdd
ON xd.DocNumber = xdd.DocNumber
GROUP BY xd.DocNumber
) y
ON xd2.DocNumber = y.DocNumber
WHEN MATCHED THEN
UPDATE SET xd2.ContractQty = y.TotalAmountQty
As I did not fully understand your scenario, this probably does not do what you want, but it should give you an idea on how to use MERGE

Update with Sub Query Derived Table Error

I have the following SQL statement to simply update the #temp temp table with the latest package version number in our Sybase 15 database.
UPDATE t
SET versionId = l.latestVersion
FROM #temp t INNER JOIN (SELECT gp.packageId
, MAX(gp.versionId) latestVersion
FROM Group_Packages gp
WHERE gp.groupId IN (SELECT groupId
FROM User_Group
WHERE userXpId = 'someUser')
GROUP BY gp.packageId) l
ON t.packageId = l.packageId
To me (mainly Oracle & SQL Server experience more than Sybase) there is little wrong with this statement. However, Sybase throws an exception:
You cannot use a derived table in the FROM clause of an UPDATE or DELETE statement.
Now, I don't get what the problem is here. I assume it is because of the aggregation / GROUP BY being used. Of course, I could put the sub query in a temp table and join on it but I really want to know what the 'correct' method should be and what the hell is wrong.
Any ideas or guidance would be much appreciated.
It seems that SYBASE doesn't support nested queries in UPDATE FROM class. Similar problem
Try to use this:
UPDATE #temp
SET versionId = (SELECT MAX(gp.versionId) latestVersion
FROM Group_Packages gp
WHERE gp.packageId=#temp.packageId
and
gp.groupId IN (SELECT groupId
FROM User_Group
WHERE userXpId = 'someUser')
)
And also what if l.latestVersion is NULL? Do you want update #temp with null ? if not then add WHERE:
WHERE (SELECT MAX(gp.versionId)
....
) is not null
I guess this is a limitation of Sybase (not allowing derived tables) in the FROM clause of the UPDATE. Perhaps you can rewrite like this:
UPDATE t
SET t.versionId = l.versionId
FROM #temp t
INNER JOIN
Group_Packages l
ON t.packageId = l.packageId
WHERE
l.groupId IN ( SELECT groupId
FROM User_Group
WHERE userXpId = 'someUser')
AND
l.versionId =
( SELECT MAX(gp.versionId)
FROM Group_Packages gp
WHERE gp.groupId IN ( SELECT groupId
FROM User_Group
WHERE userXpId = 'someUser')
AND gp.packageId = l.packageId
) ;
Your table alias for #temp is called "t" and your original table is called "t".
My guess is that this is the problem.
I think you want to start with:
update #temp
Does this syntax work in Sybase?
update dstTable T
set (T.field1, T.field2, T.field3) =
(select S.value1, S.value2, S.value3
from srcTable S
where S.key = T.Key);
I believe the correlated subquery can be as complicated as you like (including using CTE. etc). It just has to project the right number (and type) of values.

SQL Query to get and update today and yesterday's data?

Alright, I have to create a similar table structure to mine more simplified -
Test_Table: EmployeeId,Points,Date
Test_Table1:Score,EmployeeId,Date
Leaderboards_Table: Points,Score,EmployeeId,Day,Month,Year
Now I need to write a single query to update or insert into LeaderBoards_Table something like -
UPDATE Leaderboards_Table
SET Points=pts,Score=total_score
FROM
(
(SELECT
(SELECT SCORE from Test_Table1 WHERE Employee = #EmployeeId AND DAY(DATE)=10 AND MONTH(DATE)=12 AND YEAR(DATE)=2010) as pts
)
Points as pts
from Test_Table where Employee = #EmployeeId AND DAY(DATE)=10 AND MONTH(DATE)=12 AND YEAR(DATE)=2010
)
WHERE EmployeeId=#EmployeeId and DAY=10 AND MONTH=12 AND YEAR=2010
Now the above query only updates for today...what I want to do is also update yesterday
also in a single query I dont want to write another query....so is there anyway to do a single query to update yesterday and today's points.
UPDATE: Also this query will be called lot of times..so it would be great to have the most performance effective query for this.
Its a lot easier if you change to joins instead of subqueries.
UPDATE Leaderboards_Table
SET
Points=t1.score,
Score=total_score
FROM
Leaderboards_Table lt
INNER JOIN Test_Table1 t1
ON lt.employee_ID = t1.employee_id
INNER JOIN Test_Table t
ON lt.employee_ID = t1.employee_id
and lt.date = t1.date
WHERE
EmployeeId=#EmployeeId and DAY IN (9,10) AND MONTH=12 AND YEAR=2010
Here's a solution that uses the BETWEEEN clause.
UPDATE Leaderboards_Table
SET Points=tt.Points, Score = tt1.Score
FROM LeaderBoards_Table
JOIN Test_Table1 tt1 ON LeaderBoards_Table.EmployeeId = tt1.EmployeeId
JOIN Test_Table tt ON tt1.EmployeeId = tt.EmployeeId
WHERE EmployeeId = #EmployeeId
AND CONVERT(datetime CAST(YEAR AS varchar) + CAST(MONTH AS varchar) + CAST(DAY AS varchar))
BETWEEN '20101209' AND '20101210'