How return two equal max values for the same country when the query is grouped by the country? - sql

For example I have to write a query that shows the customer who had spent the most in each country but if a country has two customers with same max value i have to show them both in the output.
I have wrote the query that return the maximum value for each customer in each country but the last country in my example which is 'United Kingdom' has two customers with same maximum values and i couldn't show them both.
SELECT c1.CustomerId, c1.FirstName,c1.LastName,c1.Country,
MAX(c1.TotalSpent) as TotalSpent
FROM
(SELECT c.CustomerId,c.FirstName, c.LastName,i.BillingCountry
Country, SUM(i.Total) totalspent
FROM Customer c
JOIN Invoice i
ON c.CustomerId = i.CustomerId
GROUP BY 1
ORDER BY totalspent
) c1
GROUP BY 4
ORDER BY Country

Use window functions!:
SELECT c.*
FROM (SELECT c.CustomerId, c.FirstName, c.LastName, i.BillingCountry as Country,
SUM(i.Total) as totalspent,
DENSE_RANK() OVER (PARTITION BY i.BillingCountry ORDER BY SUM(i.Total) DESC) as seqnum
FROM Customer c JOIN
Invoice i
ON c.CustomerId = i.CustomerId
GROUP BY c.CustomerId, c.FirstName, c.LastName, i.BillingCountry
) c
WHERE seqnum = 1
ORDER BY Country;
This also fixes your GROUP BY clauses so they are consistent with the columns being selected.

Related

What customers who bought the biggest amount of a product in one order?

I have 2 tables:
CUSTOMERS (ID, FIRSTNAME, LASTNAME, ADDRESS);
ORDERS (ID, PRODUCT_NAME, PRODUCT_PRICE, DATE_ORDER DATE, ID_CUSTOMER, AMOUNT);
Get the first and last names of the customers who bought the biggest amount of a product in one order.
The orders without customer should not be considered. Please sort by FIRSTNAME and LASTNAME
SELECT firstname, lastname
FROM customers
LEFT JOIN orders ON customers.id = orders.id_customer
GROUP BY customers.firstname
HAVING (SELECT MAX(orders.amount) FROM orders);
What I'm doing wrong? thx
If you want one customer with the largest value of amount, then simplest method is order by and then fetching only one row:
select c.firstname, c.lastname
from customers c join
orders o
on c.id = o.id_customer
order by o.amount desc
fetch first 1 row only;
If you want the biggest amount per product, then window functions are the right approach
select pc.*
from (select o.product, c.firstname, c.lastname, o.amount,
rank() over (partition by o.product order by o.amount desc) as seqnum
from customers c join
orders o
on c.id = o.id_customer
) pc
where seqnum = 1;

Find the highest amount although there are more than one achieving the same amount

I want to find the best customer for each country despite there is one country has two customers the same amount, I want them both to appear.
select customerid,firstname,lastname,country, max(total_amt)
from (select invoice.customerid, customer.firstname,lastname,
sum(invoice.total)total_amt,customer.country
from invoice
join customer
on customer.customerid= invoice.customerid
group by invoice.customerid,customer.country)t2
group by country;
Use window functions:
select c.*
from (select c.country, c.customerid, c.firstname c.lastname, sum(i.total) as total,
dense_rank() over (partition by c.country order by sum(i.total) desc) as seqnum
from customer c join
invoice i
on c.customerid = i.customerid
) c
where seqnum = 1;
Note that I also introduced window functions so the query is easier to write and to read.

Max after group by with sum

I’m trying to get from this two tables customer and invoice this information: the total from invoice for every year for each country! So what I wrote is:
SELECT SUM(i.total) AS Total_invoice, strftime(‘%Y’, i.InvoiceDate) AS year, c.country
FROM invoice i JOIN
customer c
ON i.CustomerId = c.CustomerId
GROUP BY 2,3
ORDER BY 1 DESC;
So I get the total of invoice for each year! Now if I want the max(total) for each country how do you do? For example I’d like to have for each country the max( total), the year and the country! Could you help? Tha k you very much enter image description here
For example I’d like to have for each country the max( total), the year and the country!
For this, use window functions:
SELECT yc.*
FROM (SELECT SUM(i.total) AS Total_invoice, strftime(‘%Y’, i.InvoiceDate) AS year, c.country,
ROW_NUMBER() OVER (PARTITION BY c.country ORDER BY SUM(i.total) DESC) as seqnum
FROM invoice i JOIN
customer c
ON i.CustomerId = c.CustomerId
GROUP BY 2, 3
) yc
WHERE seqnum = 1
ORDER BY 1 DESC;

I need a solution to this SQL Query I'm trying to solve

"Write a query that determines the customer that has spent the most on
music for each country. Write a query that returns the country along
with the top customer and how much they spent. For countries where the
top amount spent is shared, provide all customers who spent this
amount.
You should only need to use the Customer and Invoice tables.
Check Your Solution
Though there are only 24 countries, your query should return 25 rows
because the United Kingdom has 2 customers that share the maximum."
You can find the data set here
.
Here is the code I tried with the results
And here is the expected outcome
Generally, you should always GROUP BY anything in your SELECT that is not an aggregation function (e.g. SUM). Try this:
SELECT c.CustomerId, c.FirstName, c.LastName, c.Country,
SUM(i.Total) AS TotalSpent
FROM Customer c
JOIN Invoice i
ON i.CustomerId = c.CustomerId
GROUP BY c.CustomerId, c.FirstName, c.LastName, c.Country
ORDER BY c.Country
WITH tab1 AS ( SELECT c.CustomerId, c.FirstName, c.LastName, c.Country, SUM(i.Total) TotalSpent FROM Customer c JOIN Invoice i ON c.CustomerId = i.CustomerId GROUP BY c.CustomerId ) SELECT tab1.* FROM tab1 left JOIN ( SELECT CustomerId, FirstName, LastName, Country, MAX(TotalSpent) AS TotalSpent FROM tab1 GROUP BY Country ) tab2 ON tab1.Country = tab2.Country WHERE tab1.TotalSpent = tab2.TotalSpent ORDER BY Country;

How to get two ties of maximum values in my query?

I have a database of a music store and I need to extract the max value of purchases from a customer specific to each country. While using MAX function, I noticed that I have two ties of maximum values in 'United Kingdom'. So, I need my query to return both the customers for this country.
With t1 As (
Select i.CustomerId, c.FirstName, c.LastName,
i.BillingCountry Country, Sum(i.Total) Totals
From Invoice i
Join Customer c
On c.CustomerId = i.CustomerId
GROUP BY 1, 4)
Select CustomerId, FirstName, LastName, Country, Max(Totals) TotalSpent
From t1
Group By 4;
This is the output
This is what the output should be
I tried using TOP but apparently by workspace does not accept this function. So, Please suggest a solution that does not use this function.
Thanks in advance.
I would consider something like
With t1 As (
Select i.CustomerId, c.FirstName, c.LastName,
i.BillingCountry Country, Sum(i.Total) Totals
From Invoice i
Join Customer c
On c.CustomerId = i.CustomerId
GROUP BY 1, 4)
Select CustomerId, FirstName, LastName, Country, Totals TotalSpent
From t1
WHERE t1.Total = (SELECT MAX(Totals) FROM t1 t2 WHERE t1.Country = t2.Country)
Group By 4;
(I've changed MAX(Totals) to Totals in your main query's SELECT statement and added the WHERE clause)
or
With t1 As (
Select i.CustomerId, c.FirstName, c.LastName,
i.BillingCountry Country, Sum(i.Total) Totals
From Invoice i
Join Customer c
On c.CustomerId = i.CustomerId
GROUP BY 1, 4),
t2 as (
SELECT Country, MAX(Totals) as Totals
FROM t1
GROUP BY Country
)
Select t1.CustomerId, t1.FirstName, t1.LastName, t1.Country, t1.Totals TotalSpent
From t1 INNER JOIN t2
on t1.Country = t2.Country and t1.Totals = t2.Totals
Group By 4;
(I've added the t2 CTE, joined it into your main query, and adjusted the main SELECT accordingly)
In both cases, I'm trying to select all the customer information where that customer's total is equal to the maximum total for their country. In principle, this should work no matter how many ties there are.
Use window functions!
select CustomerId, FirstName, LastName,
Country, Totals
from (select i.CustomerId, c.FirstName, c.LastName,
i.BillingCountry as Country, sum(i.Total) as Totals,
rank() over (partition by i.BillingCountry over sum(i.Total) desc) as seqnum
from Invoice i join
Customer c
on c.CustomerId = i.CustomerId
group by i.CustomerId, c.FirstName, c.LastName,
i.BillingCountry
) ic
where seqnum = 1;