group by, order by, distinct together - sql-server-2008

I have table with three columns (Trader, Product, Price). I want to get each Trader once and Product with max price to that Trader. When I select following I see repeated Traders:
select Trader, Product, Max(Price) as Price
from dbo.Sell
group by Trader, Product
order by Max(Price) desc
How can distinct Trader for the query above? The query below doesn't change anything:
select distinct Trader, Product, Max(Price) as Price
from dbo.Sell
group by Trader, Product
order by Max(Price) desc
Actually the following query does almost I want, however I want to see Product instead of Price.
select Trader, Max(Price) as Price
from dbo.Sell
group by Trader

Try this query, you would get multiple records only if a trader has more than one product with max price.
;with cte as (
select Trader, Max(Price) as Price
from dbo.Sell
group by Trader
)
select cte.Trader, s.Product, cte.Price
from cte join dbo.Sell s
on cte.Trader = s.Trader and cte.Price = s.Price
order by cte.Price desc
Second method would be to use a rank() function, but again rank() function will bring multiple records for same price records.
To get a single record, you can use Row_Number() in place of Rank().
;with cte as (
select Trader, Product, Price,
Rank() over (partition by Trader order by Price desc) rnk
from dbo.Sell
)
Select Trader, Product, Price
From cte
Where rnk = 1
Order by Price desc

Related

How can i group by but select only the top 10 under each group by sum?

I have what i tihnk is a complicated question... the query below is usally exported into excel:
select
shop_type,
shop_name,
company,
sum(amount) as amount,
sum(counts) as count,
from df
group by shop_type,shop_name,company
company is only of two values A, B. The priblem is that when i run the above and throw this into a pivot i am unable to do so because it's so large e.g. 5 million rows.. when i put this into a pivot my rows are shop_type, shop_name (with shop name nested under shop_type) and my columns are company, i then sort by grand total (largest to smallest) whilst also sorting from largest to smallest for each shop_name under shop_type!
How can i run the above but select only the top 10 shop_names u (those with largest share of amount) under each shop_type for both companies (i.e. total)?
Use window functions:
select df.*
from (select shop_type, shop_name, company,
sum(amount) as amount, sum(counts) as count,
row_number() over (partition by company, shop_type order by sum(amount) desc) as seqnum
from df
group by shop_type,s hop_name, company
) df
where seqnum <= 10;
Note: Your question is also tagged Hive. The above is standard SQL, but Hive might be quirky about mixing aggregation and window functions. If so, you can use one more level of subqueries:
select df.*
from (select df.*
row_number() over (partition by company, shop_type order by sum(amount) desc) as seqnum
from (select shop_type, shop_name, company,
sum(amount) as amount, sum(counts) as count
from df
group by shop_type,s hop_name, company
) df
) df
where seqnum <= 10;

How to SELECT based on grouped SUM that is compared to the AVG of that grouped SUM

I have a table consists of films, categories and prices.
Now I want to select only categories with total price (sum of all the price per film under that category) that is higher than the average of those categories' total prices.
I have been able to find the average of the total prices (thanks to this web) but can't combine it together.
Here are the queries:
-- Return the average sums of the price per category
SELECT AVG(sum_price)
FROM
(
SELECT category, sum(price) AS sum_price
FROM film_list
GROUP BY category
) AS inner_query;
-- Return category and its total price
SELECT category, SUM(price)
FROM film_list
GROUP BY category;
--[Error] Return only the category with sums of price larger than the average of sum of prices
SELECT category, SUM(price)
FROM film_list
WHERE SUM(price) >
(
SELECT AVG(sum_price)
FROM
(
SELECT category, sum(price) AS sum_price
FROM film_list
GROUP BY category
) AS inner_query
);
Any help will be much appreciated, thanks!
Try adding group by and then using having
SELECT category, SUM(price)
FROM film_list
GROUP BY category
HAVING SUM(price) >
(
SELECT AVG(sum_price)
FROM
(
SELECT category, sum(price) AS sum_price
FROM film_list
GROUP BY category
) AS inner_query
);
This is most easily solved using window functions:
SELECT c.*
FROM (SELECT category, SUM(price) AS sum_price,
AVG(SUM(price)) OVER () as avg_total_price
FROM film_list
GROUP BY category
) c
WHERE sum_price > avg_total_price

SQL SELECT MIN value with WHERE statement

I'm trying to get the lowest price of a specific quote on SQL. I tried the following with erroneous results:
SELECT * FROM price WHERE price=(SELECT MIN(price) as price FROM price WHERE id_quote=36
SELECT id_provider, MIN(price) as price FROM price WHERE id_quote=36
I understand that I'm getting multiple results on the first query if I have the same price in that table regardless of the quote. But I don't know why the second isn't giving me the correct results.
I need to call only id_provider and its price from that specific quote (no group).
Any help?
I think you just need a correlated subquery:
SELECT p.*
FROM price p
WHERE p.id_quote = 36 AND
p.price = (SELECT MIN(p2.price) FROM price p2 WHERE p2.id_quote = p.id_quote);
Notice that the "quote" condition has moved to the outer query.
I like using RANK() for this kind of problem:
SELECT id_quote, id_provider, price
FROM
(
SELECT id_quote id_provider, price,
RANK() OVER(PARTITION BY id_quote ORDER BY price ASC) AS rnk
FROM price
) sub
WHERE rnk = 1
You can do it this way if you want:
SELECT TOP 1 id_provider, price FROM price WHERE id_quote=36 ORDER BY price ASC

SELECT the customer who has ordered the greatest quantity of Products in the case of two customers

I have the following ORDERS table
I know query to select the customer that has ordered the greatest quantity. However, how would it work, if say, two customers have the same quantity. What query should I write to show both the customers?
You can use a subquery which checks that the quantity for a given record matches the largest quantity observed in the table:
SELECT *
FROM yourTable
WHERE qty = (SELECT MAX(qty) FROM yourTable)
This will return multiple records if there are more than one customer sharing the maximum quantity.
If you only wanted to get back a single record, even in the presence of ties, you could use this approach:
SELECT *
FROM yourTable
ORDER BY qty DESC
LIMIT 1
I think you want sum of qty per custNum.
If so you can try like:
select custNum,
sum(qty) as qty
from Orders
group by custNum
order by sum(qty) desc;
Fiddle here:
http://sqlfiddle.com/#!9/47931b/10
SELECT custnum,sum(qty) as total
FROM orders
group by custnum
having sum(qty) = (SELECT MAX(qty) FROM orders);
This will return both values.

Not sure how to write a simple query

Hi I Have a table which has number of products and rating for each, due to some reasons I have different row of each product along with rate of each person who rated it, as following:
p1 2
p2 4
p3 4
p1 4
p1 5
p1 3
p2 7
I am using following query but it shows the average rate of all products, but I am expecting it to show the average rate of each product seperately.
Select ProductName, AVG(Rate) FROM Products
Just GROUP BY productName:
Select ProductName, AVG(Rate) AS 'Average Rate'
FROM Products
GROUP BY productName
Edit: To show the one with highest rate:
SELECT ProductName, Rate
FROM Products
ORDER BY rate DESC
LIMIT 1
Edit 2: To get the product name with the highest average rate:
SELECT productname, AVG(rate) Avgrate
FROM Products
GROUP BY productname
HAVING AVG(rate) =
(
SELECT AVG(rate)
FROM Products
GROUP BY productname
ORDER BY AVG(rate) DESC
LIMIT 1
)
You need to add Group By.
Select ProductName, AVG(Rate) FROM Products GROUP BY ProductName
To Sort Result use Order By after Group By
Select ProductName, AVG(Rate) FROM Products GROUP BY ProductName ORDER BY ProductName
Above query sort result in Ascending order if you want to sort descending then use DESC,
Select ProductName, AVG(Rate) FROM Products GROUP BY ProductName ORDER BY ProductName DESC
To Select Higher Rating Product
Select ProductName, AVG(Rate) FROM Products GROUP BY ProductName
HAVING AVG(Rate) = (SELECT MAX(AVG(Rate)) FROM Products GROUP BY ProductName)
This query return all product which have max average rating.
Only One Product with Higher rating use LIMIT in Descending Sort
Select ProductName, AVG(Rate) FROM Products GROUP BY ProductName
ORDER BY ProductName DESC
LIMIT 1