Subquery repeats values - mysql

I got this query to retrieve total price, average and difference but i think i am inputting the group by or order by incorrect because it shows me all the data i want except it just repeats the same customer name, cellphone and email for every result but the total price, average and difference are all different
SELECT
FirstName,
LastName,
CellPhone,
Email,
TotalPrice,
AVG(TotalPrice) AS 'Average Total Price',
TotalPrice - 'Average Total Price' AS 'Difference Total Price'
FROM
customer,
(SELECT
CID, TotalPrice
FROM
orders) AS c
GROUP BY TotalPrice
ORDER BY FirstName;

I suspect this is what you want:
SELECT
c.FirstName,
c.LastName,
c.CellPhone,
c.Email,
o.TotalPrice,
a.AvgPrice AS `Average Total Price`,
o.TotalPrice - a.AvgPrice AS `Difference Total Price`
FROM customer AS c
JOIN orders AS o ON c.ID = o.CID
JOIN (
SELECT CID, AVG(TotalPrice) AS AvgPrice
FROM orders
GROUP BY CID
) AS a ON a.CID = c.ID
ORDER BY c.FirstName
The subquery gets the average totals from all the orders of each customer. This is then joined with the rows for each order so you can get the difference.

Related

SUB TABLES WITH JOINS

What is wrong in this? I am not getting the currect Percentage.
Q. Compute the revenue generated by each customer based on their orders. -Also, show each customer's revenue as a percentage of total revenue. Sort by customer name.
SELECT C.customerName, P1.customerNumber, SUM(P1.amount) AS REVENUE,( SUM(P1.amount)/SUM(P.S))*100 AS Percentage
FROM Customers C
JOIN Payments P1
ON P1.customerNumber = C.customerNumber
JOIN
(
SELECT customerNumber AS C1, SUM(amount) AS S
FROM Payments
GROUP BY customerNumber
) P
ON P1.customerNumber=P.C1
GROUP BY P1.customerNumber, C.customerName
ORDER BY C.customerName;
Next time, please provide sample data and table structure, preferably in a SQl FIddle like this: https://www.db-fiddle.com/f/eKqDmiPuMaok7Uu3fwDKfD/1
Check if some of this queries suits your needs:
SELECT DISTINCT
Customers.CustomerNumber,
Customers.CustomerName,
SUM(Payments.Amount) OVER(PARTITION BY Customers.CustomerNumber) AS Revenue,
(SUM(Payments.Amount) OVER(PARTITION BY Customers.CustomerNumber)
/
SUM(Payments.Amount) OVER()) * 100 AS Percentage
FROM Customers
JOIN Payments ON Payments.CustomerNumber = Customers.CustomerNumber;
Or this:
SELECT Customers.CustomerNumber,
Customers.CustomerName,
SUM(Payments.Amount) Revenue,
(SUM(Payments.Amount)
/
(SELECT SUM(AMOUNT)
FROM Payments)) * 100 Percentage
FROM Customers
JOIN Payments ON Payments.CustomerNumber = Customers.CustomerNumber
GROUP BY Customers.CustomerNumber,
Customers.CustomerName

MySQL display a sum as a column

There are 2 tables customer (id, name) and orders (id, customer_id, date, price) where customer_id is the foreign key.
How would one get the top 5 individuals with the most purchases in the last 6 months?
needed output format is (customer.id, customer.name, sum(price))
select c.id, c.name, SUM(o.price) as total
from customer c inner join orders o
on c.id = o.customer_id
order by total desc limit 5;
I'm not sure why this query I have doesn't display anything
SUM() is an aggregate function that calculates the sum after a grouping operation. Try using a GROUP BY clause like this:
select c.id, c.name, SUM(o.price) as total
from customer c inner join orders o
on c.id = o.customer_id
group by c.id, c.name
order by total desc limit 5;
DB-fiddle: https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=7f5e3726d6af5a9144a03d503da5ae37

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...

SQL counting customers that have ordered the same product at least 7 times

I have the following tables
– Price (prodID, from, price)
– Product (prodID, name, quantity)
– PO (prodID, orderID, amount)
– Order (orderID, date, address, status, trackingNumber, custID, shipID)
– Shipping (shipID, company, time, price)
– Customer (custID, name)
– Address (addrID, custID, address)
I would like to find the names of customers who have bought the same item at least 7 times, if they bought the same item twice in one order I would like to count it as one. Here is my code:
SELECT C.name, COUNT(DISTINCT p.prodId) as prod_count
FROM Product P
INNER JOIN PO
ON PO.prodId = P.prodId
INNER JOIN "Order" O
ON O.orderId = PO.orderId
INNER JOIN Customer C
ON C.custId = O.custId
GROUP BY c.name
HAVING COUNT(DISTINCT p.prodId) > 6;
However, this is returning the number of unique products each customer has ordered which is not what I am looking for.
We can try using two levels of aggregation here. The first level of aggregation is by customer, order, and product, and removes duplicates should a given customer order the same product more than once within a single order. The next level of aggregation is only by customer and product, and it retains only customers who have at least one product which they purchased 7 or more times across different orders. Finally, we do a distinct select to retain each unique matching customer name.
WITH cte1 AS (
SELECT c.name, o.orderId, p.prodId
FROM Customer c
INNER JOIN "Order" o ON o.custId = c.custId
INNER JOIN PO po ON po.orderId = o.orderId
INNER JOIN Product p ON p.prodId = po.prodId
GROUP BY c.name, o.orderId, p.prodId
),
cte2 AS (
SELECT name, prodId
FROM cte1
GROUP BY name, prodId
HAVING COUNT(*) >= 7
)
SELECT DISTINCT name
FROM cte2;
As far as I see , there is no need of joining with Product table,unless you need Product name in your result.
;with CTE as(
SELECT orderId,prodId, COUNT(*) as OrderProd_Count
FROM dbo.PO
GROUP BY orderId,prodId
)
,CTE1 as(
SELECT prodId,count(*) as Prod_Count
from CTE
group by prodId
having count(*)>7
)
select c1.productid,ca.Name from CTE1 C1
inner join CTE C on c1.prodId=c1.prodId
inner join dbo.Order O on c.orderid=O.orderId
inner join Customer C on o.custid=C.custid

Getting total for Invoiced Paid and the amount owing for each client

I have tried many of the scripts that I found here but none did what I required.
I have 3 tables: clients, invoiced and payments.
I would like to:
sum all invoices per client within a date range
sum all payments for clients with in the date range then subtract payments from invoiced to show amount outstanding.
I need to add the date range and get the total if not zero.
So far my query is
select id,
(select sum(Total) from invoiced where invoiced.ClientId = clients.Id) AS Invoiced,
(select sum(Amount) from payments where payments.ClientId = clients.Id) AS Paid
FROM clients
The problem is the non existing relation between the invoice and the payments.
This makes it a bit "dirtier" ;)
Try this:
select p.id, sum(i.total), sum(p.amount), sum(i.total) - sum(p.amount) as outstanding
from
(
select c.id, coalesce(pay.amount,0) as amount
from
(select ClientId, Sum(Amount) amount from payments group by ClientId) as pay
right join clients c on c.id = pay.ClientId
) p
left join
(
select c.id, inv.total
from
(select ClientId, Sum(Total) total from invoiced group by ClientId) as inv
left join clients c on c.id = inv.ClientId
) i
on p.id = i.id
group by id
having sum(i.total) <> sum(p.amount)
;
Updated Sqlfiddle with results here