Below is the cutomerOrdersByName View:
# Returns total for each order ordered from largest to smallest.
DROP VIEW IF EXISTS customerOrdersByName;
CREATE VIEW customerOrdersByName AS
SELECT d.orderNumber
, customerName
, round(SUM(quantityOrdered * priceEach),2) total
FROM orderDetails d
INNER JOIN orders o ON o.orderNumber = d.orderNumber
INNER JOIN customers c ON c.customerNumber = o.customerNumber
GROUP BY customerName
ORDER BY total DESC;
How do I modify the customerOrdersByName view so that it groups and orders the totals by customer name and then by total from highest to lowest?
By modifying order by clause:
GROUP BY customerName
ORDER BY customerName asc, total DESC;
However, I do not get the order number in the select list. If you do not group by on it, you should also remove it from the select list.
Related
Finding the city in which the most orders were sent leads to the assignment of the city and the number of orders (the named amount column). I have 2 tables the named Customers and Orders
SELECT Customers.City,count( Orders.OrderID) as amount
FROM voodoo.Customers
inner join voodoo.Orders on Customers.CustomerID=Orders.CustomerID
group by Customers.City
having amount >= all(select count(Orders.OrderID)
from voodoo.Customers
inner join voodoo.Orders on Customers.CustomerID=Orders.CustomerID
group by Customers.City);
tables
You don't need a subquery as you can just order by amount (descending) and limit the result to 1:
SELECT Customers.City, count(Orders.OrderID) as amount
FROM voodoo.Customers INNER JOIN voodoo.Orders
ON Customers.CustomerID=Orders.CustomerID
GROUP BY Orders.OrderID
ORDER BY amount DESC
LIMIT 1;
EDIT: as Thorsten Kettner pointed out, I made a copy & paste error; the correct version would GROUP BY Customers.City.
You are looking for the order count per city, not per order. So, don't group by order, but by city. For the ranking of the cities you can use RANK or DENSE_RANK.
SELECT city, amount
FROM
(
SELECT
c.city,
COUNT(o.orderid) AS amount,
RANK() OVER (ORDER BY COUNT(o.orderid) DESC) AS rnk
FROM voodoo.customers c
INNER JOIN voodoo.orders o ON o.customerid = c.customerid
group by c.city
) counted_and_ranked
WHERE rnk = 1;
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
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
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 a question my professor gave me, on making a statement that goes like this
How many customers are “whales” i.e., have spent, in their lifetime, more than $4,000? How many are “shrimps,” having spent less than $20?
This is the online database we are using: http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_all
run this query to create another table before helping me out if you can
CREATE TABLE ByCustomerOrders AS
SELECT
o.OrderID
, p.ProductName
, p.ProductID
, Price
, Quantity
, Price * Quantity AS subtotal
, c.CustomerID
, s.SupplierID
FROM OrderDetails AS od
LEFT JOIN Orders AS o
ON od.OrderID = o.OrderID
LEFT JOIN Products AS p
ON p.ProductID = od.ProductID
LEFT JOIN Customers AS c
on c.CustomerID = o.CustomerID
LEFT JOIN Suppliers AS s
ON s.SupplierID = p.SupplierID;
I am trying to combine every customers order together grouping the sum by the customerID and then showing it in the table as a row for each customer ID and total amount they have order from subtotal
SELECT customerID, SUM(subtotal) AS 'total_money_spent' FROM ByCustomerOrders GROUP BY customerID ORDER BY 'total_money_spent' DESC LIMIT 1;
That didn't seem to work as it shows a value of 111. anyone see an issue?
You have a LIMIT 1 at the end of your statement which will only show the first result.
When you run:
SELECT customerID, SUM(subtotal) AS 'total_money_spent' FROM ByCustomerOrders GROUP BY customerID ORDER BY 'total_money_spent' DESC;
It outputs all the totals grouped