How to update ms access database table using update and sum() function? - sql

I have Two tables in my access database
table1(ID,productname,qunatity,remainder)
table2(ID,productname,sales)
these tables are related together using "product name" ,How can I update"reminder" from table1 with the value of "quantity form first table - Sum(sales) from second table"

Because update queries in MS Access require updateable status, you cannot use a direct inner join on an aggregate query. Consider using the MS Access DSum() function:
UPDATE table1
SET table1.remainder = table1.quantity -
DSum("Sales", "table2", "ProductName='" & table1.ProductName & "'")

Perform an update join by getting the SUM() first like
UPDATE a
SET a.remainder = x.SaleTotal
FROM table1 a
INNER JOIN (SELECT productname, SUM(sales) AS SaleTotal
FROM TABLE2 GROUP BY productname) x
ON a.productname = x.productname;

When you say that it's linked by the productname field please tell me in table 1 that is a foreign key. Since you already have an ID in table 2 there's no reason not to use that ID as the foreign key in table 1.
If you were to do that the update would be as simple as this:
update table1
set table1.quantity = table1.quantity - SUM( table2.sales )
from table1
inner join table2 on table1.productID = table2.productID
where table1.productID = 1;

Related

How can I turn my SELECT INNER JOIN into an UPDATE

I've been trying to turn my SELECT INNER JOIN into an UPDATE.
The query I've made in BigQuery is as follows:
SELECT tt.*
FROM `table` tt
INNER JOIN
(SELECT c_id, MIN(c_orderid) as OrderID, MIN(c_orderdate) AS MinDateTime
FROM `table`
GROUP BY c_id) groupedtt
ON tt.c_orderid = groupedtt.OrderID
AND tt.c_orderdate = groupedtt.MinDateTime
I want to turn this query into an update where it updates c_first_sale and sets it to TRUE.
The query I came up with is:
UPDATE `table` tt
SET tt.c_first_sale = TRUE
FROM `table` as dd
INNER JOIN
(SELECT c_id, MIN(c_orderid) as OrderID, MIN(c_orderdate) AS MinDateTime
FROM `table`
GROUP BY c_id) groupedtt
ON dd.c_orderid = groupedtt.OrderID
AND dd.c_orderdate = groupedtt.MinDateTime
WHERE 1 = 1
But that gives me the following error
UPDATE/MERGE must match at most one source row for each target row
I feel like I'm pretty close, but I'm getting stuck on this.
As mentioned by #Pale, this error occurs when you try to update a table by updating joins with more than one row from the FROM clause as given in this documentation. You can create a separate temporary table, perform a group by using an ID column and export the values into the temporary table. Perform join operation on both the tables using the ID column.

How to update a column in SQL using values propagated from a "select" statement

I have column that I have queried using select statement. I want to add this column onto my table. The statement is:
select vd.*, a.rate from vacation_days vd left join Algorithm a on v
d.work_days between a.day1 and a.day2 group by id
This returns a column with three rows each with decimal rate.
This is what I tried to do:
update vacation_days set vacation_days.free=vd.days_CurrYear*(select vd.*, a.rate from vacation_days vd left join Algorithm a on v d.work_days between a.day1 and a.day2 group by id) where id;
However it gives an error:
You can't specify target table 'vacation_days' for update in FROM clause
Please let me know what I am missing.
Thanks
You can use a correlated subquery:
update vacation_days
set free = days_CurrYear * (select a.rate
from Algorithm a
where vacation_days.work_days between a.day1 and a.day2
);

Sql Update Count Details after grouping

I have multiple tables in my SQL Server database.
I have one table say Table A which has fields like dispatch,filename,etc.
The second table say Table B has filedetails like filename, dispatchcount, totalcount etc.
There are many other fields in both tables but not relevant to this question.
Requirement is :
I want to update Table B dispatch count after grouping Table A customers where dispatch is Y.
As I want to update the Table B using the result of grouping should I create a temp Table of the result or please guide:
Query:
update Collation_Data set Dqty=T.count1
from (select [collation_code],count(1) as 'count1'
FROM [Tatkal].[dbo].[Tatkal_Merge] T
where Dscan='Y'
group by [collation_code]) where srno=T.[collation_code]
In SQL Server, you can use a join with an aggregation query. I want to point out that you should use left join if you want to update all rows in collation_data, even those with no matches:
update c
set c.Dqty = cm.cnt
from Collation_Data c left join
(select collation_code, count(*) as cnt
from [Tatkal].[dbo].[Tatkal_Merge] m
where Dscan = 'Y'
group by collation_code
) cm
on c.srno = cm.collation_code;
You can also do this with a correlated subquery:
update Collation_Data c
set Dqty = (select count(*)
from [Tatkal].[dbo].[Tatkal_Merge] m
where m.Dscan = 'Y' and m.collation_code = c.collation_code
);
This can be quite efficient with an index on Tatkal_Merge(collation_code, Dscan).
I want to update the Table B using the result of grouping should I create a temp Table of the result or please guide
update c
set c.Dqty=T.count1
from Collation_Data c
join
(select [collation_code],count(1) as 'count1'
FROM [Tatkal].[dbo].[Tatkal_Merge]
where Dscan='Y'
group by [collation_code])t
on c.srno=T.[collation_code]

update table using another table

i have to update total_orders of customers column to be equal to the total number of all the orders placed by the customer(in cust_order)
here is what i have tried
update (select *
from atish_customer a
inner join
(
select cust_nbr,count(cust_nbr) as count_orders
from atish_cust_order
group by cust_nbr
)c
on c.cust_nbr=a.cust_nbr)
set tot_orders=count_orders;
But this is the error i get
ORA-01779: cannot modify a column which maps to a non key-preserved table
How about this:
UPDATE customer SET total_orders = (
SELECT COUNT(*) FROM cust_order
WHERE cust_order.cust_nbr = customer.cust_nbr
)
[I'm not sure where your atish_customer and atish_customer_order comes into play...they're not shown in your diagram]
Explanation: Basically the inner select just counts the number of orders from the cust_order table for each cust_nbr. By joining the outer customer.cust_nbr to the inner cust_order.cust_nbr, each [outer] row will be updated with the correct total. This is called a correlated subquery (see here for a short tutorial).

Update using Distinct SUM

I have found a few good resources that show I should be able to merge a select query with an update, but I just can't get my head around of the correct formatting.
I have a select statement that is getting info for me, and I want to pretty much use those results to Update an account table that matches the accountID in the select query.
Here is the select statement:
SELECT DISTINCT SUM(b.workers)*tt.mealTax as MealCost,b.townID,b.accountID
FROM buildings AS b
INNER JOIN town_tax AS tt ON tt.townID = b.townID
GROUP BY b.townID,b.accountID
So in short I want the above query to be merged with:
UPDATE accounts AS a
SET a.wealth = a.wealth - MealCost
Where MealCost is the result from the select query. I am sure there is a way to put this into one, I just haven't quite been able to connect the dots to get it to run consistently without separating into two queries.
First, you don't need the distinct when you have a group by.
Second, how do you intend to link the two results? The SELECT query is returning multiple rows per account (one for each town). Presumably, the accounts table has only one row. Let's say that you wanted the average MealCost for the update.
The select query to get this is:
SELECT accountID, avg(MealCost) as avg_Mealcost
FROM (SELECT SUM(b.workers)*tt.mealTax as MealCost, b.townID, b.accountID
FROM buildings AS b INNER JOIN
town_tax AS tt
ON tt.townID = b.townID
GROUP BY b.townID,b.accountID
) a
GROUP BY accountID
Now, to put this into an update, you can use syntax like the following:
UPDATE accounts
set accounts.wealth = accounts.wealth + asum.avg_mealcost
from (SELECT accountID, avg(MealCost) as avg_Mealcost
FROM (SELECT SUM(b.workers)*tt.mealTax as MealCost, b.townID, b.accountID
FROM buildings AS b INNER JOIN
town_tax AS tt
ON tt.townID = b.townID
GROUP BY b.townID,b.accountID
) a
GROUP BY accountID
) asum
where accounts.accountid = asum.accountid
This uses SQL Server syntax, which I believe is the same as for Oracle and most other databases. Mysql puts the "from" clause before the "set" and allows an alias on "update accounts".