I've got 2 tables: Online Orders, Online orders details
I have an issue on how to calculate the total amount of the order in Online Order table based on the detail order table.
The detail table looks like:
id_order Id_product quantity price value
1 2 1 3 3
1 3 2 2 4
2 1 1 5 5
I would like to sum all the values from an id_order and insert them into the total amount of the order in the Online orders table.
Can you help me with the SQL command?
It's not clear what database system you use.
If you want to UPDATE orders.total_amount
This update statement will work under any DB:
update orders
set total_amount = (
select SUM(value)
from orders_details
where id_order = orders.id
)
where EXISTS(select *
from orders_details
where id_order = orders.id)
This update statement works under MySQL:
update orders u
inner join (select id_order, SUM(value) as total
from orders_details
GROUP BY id_order) s on
u.id = s.id_order
set u.total_amoun = s.total
Is this what you want?
SELECT o.id_order, SUM(quantity * price) AS total_price
FROM online o
INNER JOIN detail d
ON d.id_order = o.id_order
GROUP BY o.id_order
Related
I need to join 2 tables with the 2nd table with JOIN condition that is based on the 3rd JOIN table.
The problem is, I couldn't get the value from 3rd JOIN table while still joining the 2nd table.
View on DB Fiddle
Table A: users
-------
user_id INT PRIMARY
Table B: orders
-------
order_id INT PRIMARY
user_id INT
invoice_id INT
Table C: invoices
-------
invoice_id INT PRIMARY
invoice_status VARCHAR [voided, paid]
This is what I wish to do:
SELECT
A.user_id,
B.order_id,
C.invoice_id,
C.invoice_status
FROM users A
LEFT JOIN orders B
ON (B.user_id = A.user_id
AND C.invoice_status = 'paid')
LEFT JOIN invoices C
ON (C.invoice_id = B.invoice_id)
The 9th line AND C.invoice_status = 'paid') is referring to table C which has not been joined yet, so this query will cause Error in query (1054): Unknown column 'C.invoice_status' in 'on clause'
The reason I cannot have this condition in WHERE clause is because I still want to return all users records regardless of whether they have any order or 'paid' invoice or not. So adding WHERE invoice_status = 'paid' will NOT return users without any order and users with invoice_status = 'voided'.
Also, when a user has two orders linked to two different invoice records, but 1 invoice's invoice_status is 'paid', while the other is 'voided', I only want to return the 'paid' record. There can be many voided invoices, but only 1 'paid' invoice record.
By the way, this is enforced: sql_mode=only_full_group_by, so I can't do GROUP BY user_id without having some kind of aggregated or condition on order_id & invoice_id fields.
SELECT
A.user_id,
B.order_id,
C.invoice_id,
C.invoice_status
FROM users A
LEFT JOIN orders B
ON (B.user_id = A.user_id)
LEFT JOIN invoices C
ON (C.invoice_id = B.invoice_id);
user_id
order_id
invoice_id
invoice_status
1
1
1
voided
1
2
2
paid
2
3
1
voided
3
NULL
NULL
NULL
My desired result:
user_id
order_id
invoice_id
invoice_status
1
2
2
paid
2
3
1
voided
3
NULL
NULL
NULL
Each user_id must only return once, with invoice_status = 'paid' being the preferred row when there are multiple related orders.
Appreciate it if anyone has any idea how to achieve this.
Thanks!
Use ROW_NUMBER() function And number the rows according to user_id and sort according to invoice_status then fetch the first row
SELECT user_id,
order_id,
invoice_id,
invoice_status
FROM
(SELECT
A.user_id,
B.order_id,
C.invoice_id,
C.invoice_status,
ROW_NUMBER() OVER(PARTITION BY A.user_id ORDER BY C.invoice_status) AS num
FROM users A
LEFT JOIN orders B
ON (B.user_id = A.user_id)
LEFT JOIN invoices C
ON (C.invoice_id = B.invoice_id)) t
WHERE num = 1
db<>fiddle
I am able to solve it by using EXISTS thanks to ProGu's comment.
SELECT
A.user_id,
B.order_id,
C.invoice_id,
C.invoice_status
FROM users A
LEFT JOIN orders B
ON B.user_id = A.user_id
AND EXISTS( SELECT
1
FROM
invoices
WHERE
invoices.invoice_id = B.invoice_id
AND invoices.invoice_status = 'paid')
LEFT JOIN invoices C
ON C.invoice_id = B.invoice_id
user_id
order_id
invoice_id
invoice_status
1
2
2
paid
2
NULL
NULL
NULL
3
NULL
NULL
NULL
Thanks!
Here's my orders table:
I want to select all orders excluding very first order of each customer (if customer has placed multiple orders).
So if a customer e.g. 215 has total 8 orders, then I will select his all last 7 orders excluding his very first order 70000 which was placed on 10 July 2017.
But if a customer e.g. 219 had placed only one order 70007, it must be selected by the query.
Using an anti-join approach:
SELECT o1.order_id, o1.customer_id, o1.order_date, o1.order_value
FROM orders o1
LEFT JOIN
(
SELECT customer_id, MIN(order_date) AS min_order_date, COUNT(*) AS cnt
FROM orders
GROUP BY customer_id
) o2
ON o1.customer_id = o2.customer_id AND
o1.order_date = o2.min_order_date
WHERE
o2.customer_site = 1 AND
(o2.customer_id IS NULL OR
o2.cnt = 1);
The idea here is to try to match each record in orders to a record in the subquery, which contains only first order records, for each customer. If we can't find a match, then such an order record cannot be the first.
You can try below -
select order_id,customer_id,order_date,order_Value
from tablename
group by order_id,customer_id,order_date,order_Value
having count(order_id)=1
union all
select order_id,customer_id,order_date,order_Value
from tablename a where order_date not in (select min(order_date) from tablename b
where a.customer_id=b.customer_id)
Solution
Dear #Tim Biegeleisen, your answer almost done. just add HAVING COUNT(customer_id)>1
So the query is below:
SELECT o1.order_id, o1.customer_id, o1.order_date, o1.order_value
FROM orders o1
LEFT JOIN (
SELECT customer_id, MIN(order_date) AS min_order_date
FROM orders
GROUP BY customer_id
HAVING COUNT(customer_id)>1
) o2
ON o1.customer_id = o2.customer_id AND
o1.order_date = o2.min_order_date
WHERE
o2.customer_id IS NULL;
I have 2 table - orders and orderdetail.
I need to join them together and show the total. I can join them but how do I calculate the total?
SELECT *
FROM Orders as o
INNER JOIN OrderDetails as od on o.order_id = od.order_id
WHERE o.table_id = 1
select a.order_id,
order_date,
order_status,
table_id,
item_id,
item_price,
quantity,
b.item_price*b.quantity as total
from dbo.orders as a inner join dbo.orderdetails as b
on a.order_id=b.order_id
WHERE table_id = 1
Update : as you mentioned in comment if you want a computed column which automatically multiply quantity and item_price, then you need
execute this query :
ALTER TABLE dbo.orderdetails ADD Total AS (quantity* item_price);
I need some help with the following in SQL:
I have 3 tables which have the following data:
table name:customer
customer ID - 1,2,3,4,5,6
customer Name - customer 1, customer 2,customer 3, customer 4, customer 5, customer 6
table name: transactions
Transaction ID -1, 2,3,4,5,6,7,8
Product ID - 2,2,3,4,2,1,4,2
customer ID - 1,2,4,4,5,6,2,5
table name: product
Product ID - 1,2,3,4
product Name - product 1, product 2, product 3, product 4
I want to know which customer(s) bought product 3 and 4 - the result should be just the customer with an ID of 4.
I have the lines below, however it will only work for 3 OR 4 due to the IN function which means displays customer ID 4 and customer ID 2. I am not sure where to use the AND function in this scenario
select distinct c.customer ID
, c.customer Name
FROM transactions t
LEFT
JOIN customer c
on c.customer ID = t.customer ID
LEFT
JOIN product p
on p.product ID = t.product ID
where p.product ID IN (3,4)`
Thanks
Vishal
Straight forward: select customers that are both in the set of product 3 buyers and product 4 buyers:
select *
from customer
where customer_id in (select customer_id from transactions where product_id = 3)
and customer_id in (select customer_id from transactions where product_id = 4);
It is often faster, however, to query the transaction table only once (by aggregating it by customer).
select *
from customer
where customer_id in
(
select customer_id
from transactions
where product_id in (3,4)
group by customer_id
having count(distinct product_id) = 2
);
use joins:
Select c.CustomerName
from Customer c join Transacation t
on c.Customer_ID = t.Customer_ID
where Product_ID in (3,4)
group by c.CustomerName
having count(distinct Product_ID) = 2
Another way, but not so optimal:
select *
from customer
where customer_id in (select customer_id from transactions where product_id = 3
INTERSECT
select customer_id from transactions where product_id = 4);
One possible query to do that is the following. The inner subquery extracts only customers who have the two products (see last WHERE A.RC=2), simulating the sort of "and condition" you need.
SELECT DISTINCT A.customer_ID, C.customer_Name
FROM (SELECT customer_ID, COUNT(DISTINCT product_ID) AS RC
FROM transactions
WHERE t.product ID IN (3,4)
GROUP BY customer_ID) A
INNER JOIN transactions t ON A.customer_ID = t.customer_ID
LEFT JOIN customer c on c.customer ID = A.customer ID
LEFT JOIN product p on p.product ID = A.product ID
WHERE A.RC=2 AND t.product ID IN (3,4)
You need this instead of IN
where p.product ID = '3' AND p.product ID ='4'
IN uses the OR logic between values thats why you're returning both
I have a question regarding the use of UNION ALL and INNER JOIN.
I found some posts regarding this issue, for example here or there but I did not manage to apply it to my issue.
What I am trying to do is to list 1) the products and 2) the difference between orders and deliveries.
I have 3 table:
product (id, name)
orders (id, product, value)
deliveries (id, product, value)
I managed to get (almost) what I want using the following:
SELECT product
, sum(total)
FROM (
SELECT product
, SUM(value) as total
FROM orders
GROUP BY product
union all
SELECT product
, -1 * SUM(value) as total
FROM deliveries
GROUP BY product)
as alias
GROUP BY product
ORDER BY sum(total) DESC
I obtain the following:
1 23
2 33
When I would like to get:
computer 23
car 33
Meaning the product name instead of the product id.
Anyone would have a solution for that? (my INNER JOIN OR LEFT JOIN attempts failed so far)
Thanks and regards
Join in the product table:
SELECT p.name, sum(total)
FROM (SELECT o.product, SUM(o.value) as total
FROM orders o
GROUP BY o.product
union all
SELECT d.product, -1 * SUM(d.value) as total
FROM deliveries d GROUP BY d.product
) od JOIN
product p
on od.product = p.id
GROUP BY p.name
ORDER BY sum(total) DESC