Why this code showing invalid use of group function? - mysql

CREATE VIEW SALESMAN_WITH_MAX_ORDER AS
(SELECT S.Salesman_id,
S.Name,
S.City,
Commission
FROM SALESMAN S,
CUSTOMER C
WHERE S.Salesman_id=C.Salesman_id
AND Customer_id IN (SELECT Customer_id
FROM ORDERS
GROUP BY Customer_id,
Ord_Date
HAVING SUM(PURCHASE_AMT) = (SELECT MAX(SUM(PURCHASE_AMT))
FROM ORDERS
GROUP BY Customer_id,
Ord_Date)));

You have a problem in the innermost query. You cannot do a MAX with a SUM as argument.
This is how you would do it in T-SQL, sorry I have no mysql to test it on right now.
CREATE VIEW SALESMAN_WITH_MAX_ORDER AS
(
SELECT S.Salesman_id,
S.Name,
S.City,
Commission
FROM SALESMAN S,
CUSTOMER C
WHERE S.Salesman_id=C.Salesman_id
AND Customer_id IN
(
SELECT Customer_id
FROM ORDERS
GROUP BY Customer_id,Ord_Date
HAVING SUM(PURCHASE_AMT)=
(
SELECT MAX(SUM_AMT)
FROM
(
SELECT SUM(PURCHASE_AMT) AS SUM_AMT
FROM ORDERS
GROUP BY Customer_id,Ord_Date
) innerTableName
)
)
);

Related

Orders that have not yet been paid mysql

I am stuck with the following problem: I would like to return from my query the orders which have yet to be paid with the amount of the order and my customer information.
Here is what the tables look like:
Taking the case of customer number 124. I can see that this one has placed 13 orders. But I only have 7 checks registered
And I can see that if I add the sum of the orders minus the sum of the payments I find a difference that corresponds to the last 3 orders that this customer has placed.
So the question is how do I bring out the commands 10382, 10371, 10368 with all that? Knowing that the solution must be able to be applied to all orders.
So I thought to myself maybe using the order and payment dates. What orders does my customer place between their last payment and today?
So I tried something like this
#last order date
WITH last_cmd AS
(
SELECT
customerNumber, od.orderNumber, orderDate last_orderDate,
shippedDate, SUM(quantityOrdered * priceEach) totcmd
FROM
orders o
LEFT JOIN
orderdetails od ON o.orderNumber = od.orderNumber
WHERE
status NOT LIKE 'Can%'
GROUP BY
orderDate
ORDER BY
customerNumber, orderDate DESC
),
#last payment date last_payment AS
(
SELECT
customerNumber, amount, paymentDate, checkNumber
FROM
payments
GROUP BY
paymentDate
ORDER BY
customerNumber, paymentDate DESC
)
SELECT *
FROM last_cmd lc
LEFT JOIN last_payment lp ON lc.customerNumber = lp.customerNumber
GROUP BY lc.orderNumber
HAVING MAX(paymentDate) NOT BETWEEN MAX(last_orderDate) AND NOW();
But as you can see the result is not really what is expected. Still taking customer 124 as an example, command 10382 does not appear. And when I do the comparison of other orders manually for other customers the results do not match.
Does anyone have an idea please?
Here is the query I tried before posting
WITH ALL_PAYMENTS AS (
WITH paymentsValues AS (
select customerNumber, checkNumber, YEAR(paymentDate) paymentYear, sum(amount) paymentValue
from payments
LEFT JOIN customers USING (customerNumber)
GROUP BY customerNumber, paymentYear)
SELECT
customerNumber,
checkNumber, #Cumul des commandes clients
paymentYear,
SUM(paymentValue) totalPaymentsValue
FROM
paymentsValues
GROUP BY
customerNumber,
checkNumber
WITH ROLLUP
HAVING checkNumber is null),
ALL_ORDERS AS(
WITH ordersValues AS (
select customerNumber, orderNumber, YEAR(orderDate) orderYear, sum(quantityOrdered*priceEach) AS orderValue
from orderdetails
LEFT JOIN orders USING (orderNumber)
GROUP BY orderNumber, orderYear)
SELECT
customerNumber,
orderNumber, #Cumul des commandes clients
orderYear,
SUM(orderValue) totalOrderValue
FROM
ordersValues
#where orderNumber = '10179'
GROUP BY
customerNumber,
orderNumber
WITH ROLLUP
HAVING orderNumber is null)
SELECT AO.customerNumber, totalOrderValue, totalPaymentsValue, totalOrderValue-totalPaymentsValue Diff
FROM ALL_ORDERS AO
LEFT JOIN ALL_PAYMENTS AP ON AP.customerNumber=AO.customerNumber
WHERE totalOrderValue-totalPaymentsValue > 0;
This should give a list op amount that have to be paid, per date:
WITH d as (
select distinct orderDate as `date` from orders
union
select distinct paymentDate as `date` from payments)
select
`date`,
`customerNumber`,
`ordersValue`,
`amountPayed`,
`ordersValue` - `amountPayed` NotPayed
from (
select
d.`date` as "date",
o.customerNumber as "customerNumber",
sum(quantityOrders*priceEach) ordersValue,
(select sum(amount)
from payments p
where o.customerNumber = p.customerNumber AND p.paymentDate <= d.`date`) as amountPayed
from orderdetails od
cross join d
inner join Orders o on od.orderNumber = o.orderNumber AND o.orderDate <= d.`date`
group by d.`date`, o.customerNumber
) orderListPerCustomer
WHERE `customerNumber` = 124
ORDER BY `date` DESC
;
It is impossible to add order info, because there is no order info in the payments
This query does not take into account the status of the order (which might be Cancelled)
NOTE: This code is not tested, so there could be typing errors...

How do I find the associated name of a max of a sum in a MySQL query?

I have this schema here, and I need to find the name of the customer with the highest total amount for the orders. I have a SQL query here:
SELECT Name
FROM (SELECT Name, SUM(Amount) AS Total
FROM customer JOIN orders ON cust_id = ID
GROUP BY Name) AS Totals
WHERE Total = (SELECT MAX(Total)
FROM (SELECT Name, SUM(Amount) AS Total
FROM customer JOIN orders ON cust_id = ID
GROUP BY Name) AS X);
But this is very inefficient as it creates the same table twice. Is there any more efficient way to get the name?
If you want customer with the greatest total mount, then you can just join, order by and limit:
select c.name
from customer c
inner join orders o on o.cust_id = c.id
group by c.id, c.name
order by sum(o.amount) desc
limit 1
Note that this does not handle possible top ties. For this, you need a little more code. Instead of ordering, you would typically filter with a having clause:
select c.name
from customer c
inner join orders o on o.cust_id = c.id
group by c.id, c.name
having sum(o.amount) = (
select sum(o1.amount)
from orders o1
group by cust_id
order by sum(o1.amount) desc
limit 1
)
Finally: if you are running MySQL 8.0, this is simpler done with window function rank():
select name
from (
select c.name, rank() over(order by sum(o.amount) desc) rn
from customer c
inner join orders o on o.cust_id = c.id
group by c.id, c.name
) t
where rn = 1

SQL query with Highest value with tie

I am trying to write a query that lists students who have earned the highest total credit in each department. I have to also include tied students in the result.
The query should return relation with department name, student name and total credit they earned.
SELECT s.dept_name, s.name, s.max
FROM (SELECT dept_name, name, MAX(tot_cred) as max
FROM university.student GROUP BY dept_name) as s,
university.student as t
WHERE s.name = t.name;
It is giving errors and I don't know how to deal with ties.
If I delete the name part in the query, I have managed to get the highest credits in each department(without a tie)
The table student consists of an ID, name, department, total credit.
Use RANK() window function:
SELECT t.dept_name, t.name, t.tot_cred
FROM (
SELECT dept_name, name, tot_cred,
RANK() OVER(PARTITION BY dept_name ORDER BY tot_cred DESC) rn
FROM university.student
) t
WHERE t.rn = 1
This is an alternative in case you can't use window functions:
SELECT s.dept_name, s.name, s.tot_cred
FROM university.student s
INNER JOIN (
SELECT dept_name, MAX(tot_cred) tot_cred
FROM university.student
GROUP BY dept_name
) t ON t.dept_name = s.dept_name AND s.tot_cred = t.tot_cred
or with NOT EXISTS:
SELECT s.dept_name, s.name, s.tot_cred
FROM university.student s
WHERE NOT EXISTS (
SELECT 1 FROM university.student
WHERE dept_name = s.dept_name AND tot_cred > s.tot_cred
)

MySQL Workbench reports an error Code: 1064 in MySQL

SELECT OrderID, OrderDate, Freight
FROM orders
WHERE CustomerID IN (SELECT CustomerID FROM WHERE City in ('Germany', 'Mexico', 'Spain'))
ORDER BY Freight DESC;
Your inner SELECT clause has a from with out a table.
I added orders2 as tablename because i don't know exactly what you have in mind
SELECT OrderID, OrderDate, Freight
FROM orders
WHERE CustomerID IN (SELECT CustomerID FROM orders2 WHERE City in ('Germany', 'Mexico', 'Spain'))
ORDER BY Freight DESC;
Question is not clear but if only one table is involved, I think this is a simple form.
SELECT OrderID, OrderDate, Freight
FROM orders
WHERE City IN ('Germany', 'Mexico', 'Spain'))
ORDER BY Freight DESC;
or if there are two tables
SELECT a.OrderID, a.OrderDate, a.Freight
FROM orders a, orders2 b
WHERE a.CustomerID=b.CustomerID AND b.city IN ('Germany', 'Mexico', 'Spain'))
ORDER BY a.Freight DESC;
A join may also be used.

mysql sum results after each sum

Hello I'm trying to sum the result of two mysql result.
This is my code, it doesn't work.
SELECT
a.* ,
b.* ,
SUM(b.price) as price,
SUM(b.tax) as tax,
price + tax as price_tax --> error
FROM (SELECT name , item_id
FROM items)a
LEFT JOIN (SELECT item_id , price , tax
FROM bank
)b
ON a.item_id = b.item_id
GROUP BY item_id
I want to sum the two results like this: price + tax as price_tax
First
The SQL engine don't know the column alias in select clause during (the specific) query execution so
you can't use alias you must repeat the code
SELECT
SUM(b.price) as price,
SUM(b.tax) as tax,
SUM(b.price) + SUM(b.tax) as price_tax
FROM (
SELECT name , item_id
FROM items
)a
LEFT JOIN (
SELECT item_id , price , tax
FROM bank
)b
ON a.item_id = b.item_id
GROUP BY item_id
Second
in some mysql version is not allowed the use of aggregation function and select column not mentioned in group by so you must remove the column not mention in group by (or add fake aggreation function ) for the others columns
SELECT
a.item ,
SUM(b.price) as price,
SUM(b.tax) as tax,
SUM(b.price) + SUM(b.tax) as price_tax
FROM (
SELECT name , item_id
FROM items
)a
LEFT JOIN (
SELECT item_id , price , tax
FROM bank
)b
ON a.item_id = b.item_id
GROUP BY item_id