Oracle SQL return sum of multiple across tables - sql

Farily new to SQL and the IT world, and always do a lot of work before asking for help but this time I am stumped.
I have three tables:
So I am trying to update the "payment_owed" table by doing the following:
For each customer, get the food_id and quantity, then using the food_id multiply the quantity by the cost.
The best I have done this far is a natural join on the tables, and attempting to sum the quantity * cost for each ID
My understanding for updating a specific customer:
update customer
set payment_owed = (select <quantity>) * (select <cost>)
where cust_no = 1;
If im not on the right forum or there's a better place to ask these questions let me know, thank you for your time!

Simply:
update customer
set payment_owed = (SELECT SUM(o.cost*s.quantity)
FROM order o JOIN session s ON s.food_id = o.food_id
WHERE s.cust_no = customer.cust_no)
where cust_no = 1;
Anyway will you update it after every change on table? How about using view like:
CREATE VIEW my_view AS
SELECT cust_no, SUM(o.cost*s.quantity)
FROM order o
JOIN session s ON s.food_id = o.food_id
GROUP BY cust_no;

Related

SQL oracle How can i multiply two columns from different tables and put the resulting column in one of the two tables

I am currently working on an SQL project and my code just won't work this is what I tried
UPDATE detail_order
SET total = (
SELECT (detail_order.quantity*product.PRICE_EXCLVAT)
FROM detail_order,product
where detail_order.npro=product.npro
);
But oracle keeps telling me: ora-01427 single-row subquery returns more than one row. But I can't figure out how to solve this because each product has one price and each order is linked to only one product so no confusion there. Some products are ordered several times but I can't see how this could be a problem.
Should probably be something like this:
update detail_order d set
d.total = (select d.quantity * p.price_exclvat
from product p
where p.npro = d.npro
)
where exists (select null from product a
where a.npro = d.npro
);
Or
merge into detail_order d
using product p
on (p.npro = d.npro)
when matched then update set d.total = d.quantity * p.price_exclvat;
None of these will work (i.e. you'll again get too_many_rows if there are more than a single row in the product table whose npro matches detail_order's npro.
What to do then? It depends on you; we don't have your tables and we don't know what the requirement is.
I believe what you want is something like this:
update detail_order d
set total = quantity *
(select price_exclvat from product where npro = d.npro)
;
quantity is the quantity from the same row you are updating. There is no reason to reference detail_order to retrieve the quantity for that row.

My question is about SQL, using a TOP function inside a sub-query in MS Access

Overall what I'm trying to achieve is a query that shows the most ordered item from a customer in a database. To achieve this I've tried making a query showing how many times a customer has ordered an item, and now I am trying to create a sub-query in it using TOP1 to discern the most bought items.
With the SQL from the first query (looking weird because I made it with the Access automatic creator):
SELECT
Customers.CustomerFirstName,
Customers.CustomerLastName,
Products.ProductName,
COUNT(SalesQuantity.ProductCode) AS CountOfProductCode
FROM (Employees
INNER JOIN (Customers
INNER JOIN Sales
ON Customers.CustomerCode = Sales.CustomerCode)
ON Employees.EmployeeCode = Sales.EmployeeCode)
INNER JOIN (Products
INNER JOIN SalesQuantity
ON Products.ProductCode = SalesQuantity.ProductCode)
ON Sales.SalesCode = SalesQuantity.SalesCode
GROUP BY
Customers.CustomerFirstName,
Customers.CustomerLastName,
Products.ProductName
ORDER BY
COUNT(SalesQuantity.ProductCode) DESC;
I have tried putting in a subquery after FROM line:
(SELECT TOP1 CountOfProduct(s)
FROM (.....)
ORDER by Count(SalesQuantity.ProductCode) DESC)
I'm just not sure what to put in for the "from"-every other tutorial has the data from an already created table, however this is from a query that is being made at the same time. Just messing around I've put "FROM" and then listed every table, as well as
FROM Count(SalesQuantity.ProductCode)
just because I've seen that in the order by from the other code, and assume that the query is discerning from this count. Both tries have ended with an error in the syntax of the "FROM" line.
I'm new to SQL so sorry if it's blatantly obvious, but any help would be greatly appreciated.
Thanks
As I understand, you want the most purchased product for each customer.
So, begin by building aggregate query that counts product purchases by customer (appears to be done in the posted image). Including customer ID in the query would simplify the next step which is to build another query with TOP N nested query.
Part of what complicates this is unique record identifier is lost because of aggregation. Have to use other fields from the aggregate query to provide unique identifier. Consider:
SELECT * FROM Query1 WHERE CustomerID & ProductName IN
(SELECT TOP 1 CustomerID & ProductName FROM Query1 AS Dupe
WHERE Dupe.CustomerID = Query1.CustomerID
ORDER BY Dupe.CustomerID, Dupe.CountOfProductCode DESC);
Overall what I'm trying to achieve is a query that shows the most ordered item from a customer in a database.
This answers your question. It does not modify your query which is only tangentially related.
SELECT s.CustomerCode, sq.ProductCode, SUM(sq.quantity) as qty
FROM Sales as s INNER JOIN
SalesQuantity as sq
ON s.SalesCode = sq.SalesCode
GROUP BY s.CustomerCode, sq.ProductCode;
To get the most ordered items, you can use this twice:
SELECT s.CustomerCode, sq.ProductCode, SUM(sq.quantity) as qty
FROM Sales as s INNER JOIN
SalesQuantity as sq
ON s.SalesCode = sq.SalesCode
GROUP BY s.CustomerCode, sq.ProductCode
HAVING sq.ProductCode IN (SELECT TOP 1 sq2.ProductCode
FROM Sales as s2 INNER JOIN
SalesQuantity as sq2
ON s2.SalesCode = sq2.SalesCode
WHERE s2.CustomerCode = s.CustomerCode
GROUP BY sq2.ProductCode
);
In almost any other database, this would be simpler, because you would be able to use window functions.

How can i SUM records from a table to another after multiplying two columns

I have a table called orderItems which has two columns, quantity and unit price.It also has a foreign key ordernumber in that very table.
I have another table called ordergroup with primary key ordernumber, which contains SavedTotal column which is the order total based on quantity * unit price for all order item rows that reference that ordernumber.
Now what i struggle with is the sql query that can get all order items based on a certain ordernumber and calculate the total cost.
I have managed to do the multiplication but i am missing the SUM, here is my sql query(based on SQL Server) so far.
UPDATE OrderGroupNew
set OrderGroupNew.SavedTotal = OrderItemNew.UnitPrice*OrderItemNew.QUANTITY
FROM OrderItemNew
inner join OrderGroupNew on OrderItemNew.OrderNumber=OrderGroupNew.OrderNumber
any help is appreciated
UPDATE OrderGroupNew
SET SavedTotal = (
SELECT SUM(UnitPrice * Quantity)
FROM OrderItemNew
WHERE OrderNumber = OrderGroupNew.OrderNumber
)
You can use a TVP as well :
;With o as (
select OrderItemNew.OrderNumber as OrderNumber,
SUM(OrderItemNew.UnitPrice*OrderItemNew.QUANTITY) as OrderSum
Group by OrderItemNew.OrderNumber)
UPDATE OrderGroupNew
set OrderGroupNew.SavedTotal = o.OrderSum
FROM o
INNER JOIN OrderGroupNew on o.OrderNumber=OrderGroupNew.OrderNumber
Well the 1st answer is correct too. Choose the best in term of performance :) (dont know which will be the best, to be honest ! )

Querying records that meet muliple criteria

Hi I’m trying to write a query and I’m struggling to figure out how to go about it.
I have a suppliers table and a supplier parts table I want to write a query that lists suppliers that have specified related Parts in the supplier parts table. If a supplier doesn’t have all specified related parts then they should not be listed.
At the moment I have written a very basic query that lists the supplier if they have a related supplier part that meets the criteria.
SELECT id ,name
FROM
efacdb.dbo.suppliers INNER JOIN [efacdb].[dbo].[spmatrix] ON
id = spmsupp
WHERE spmpart
IN ('ALUM_5083', 'ALUM_6082')
I only want to show the supplier if they have both parts related. Does anyone know how I could do this?
Use a subquery with counting distinct occurences:
select * from suppliers s
where 2 = (select count(distinct spmpart) from spmatrix
where id = spmsupp and spmpart in ('ALUM_5083', 'ALUM_6082'))
As a note, you can modify your query to get what you want, just by using an aggregation:
SELECT id, name
FROM efacdb.dbo.suppliers INNER JOIN
[efacdb].[dbo].[spmatrix]
ON id = spmsupp
WHERE spmpart IN ('ALUM_5083', 'ALUM_6082')
GROUP BY id, name
HAVING MIN(spmpart) <> MAX(spmpart);
If you know there are no duplicates, then having count(*) = 2 also solves the problem.

Oracle SQL Update a column based on another table but based on a date

Learning SQL so please forgive me.
I have a table that holds many accounts(and sub accounts) and another table that holds many orders they are custom tables taken from different databases.
What I am trying to do is update order_amt on the account table with the order_val value from the orders table but if there are more than one order with that account I want the order amount from the earliest order date only.
Account Table
Acc _Num..........Comp_Name.......Order_Amt.......Int_Id
123456789-1.....ABC Ltd.......................................123456789
123456789-2.....ABC Ltd.......................................123456789
987654321-1.....Xyz Ltd.........................................987654321
987654321-2.....Xyz Ltd.........................................987654321
Orders Table
Order_Num.....Order_Dt.....Order_Val.....Acc_num
1......................01/01/13......£20.00...........123456789
2......................01/01/14......£10.00...........123456789
3......................01/01/10......£100.00..........987654321
4......................01/01/11......£200.00..........987654321
So the order_amt for accounts 123456789-1 & 2 = £20.00 and from 987654321-1 & 2 would be £100.00.
UPDATE accounts a
SET a.order_amt =
(
SELECT order_val
FROM orders o
WHERE a.int_id = o.acc_num
AND EXISTS
(
SELECT MIN(order_dt)
FROM orders oa
WHERE o.order_num = oa.order_num
);
I am getting a few errors including the error that more than one row returned? Could anyone please help me?
kind Regards
Eden
I think you need something like this:
UPDATE accounts a
SET a.order_amt =
(
SELECT order_val
FROM orders o
WHERE a.int_id = o.acc_num
GROUP BY order_val
HAVING order_dt = MIN(order_dt);
);
Create a FK on the column account_number inside of the orders table and have it reference the auto-increment account id of the accounts table.
Then as Roger suggest, with the slight modification of the column int_id AND a modification of the HAVING clause
UPDATE accounts a
SET a.order_amount =
(
SELECT order_value
FROM orders o
WHERE a.account_number = o.account_number
GROUP BY order_value
HAVING MIN(order_date)
)
This will not fix the error that is occurring with more than one row being returned though since there are multiple orders with the same account id attached to them. You will need to be more specific about how what you are needing. Do you want the average of all order amounts to equal the order value in the accounts table? Or maybe the MAX/MIN value?