MySQL - Matching ID to Max of Count ("Need" more elegant solution) - mysql

Is there a better way to do the following:
SELECT ProductID, MAX(a.countProductID)
FROM
(
SELECT ProductID, COUNT(ProductID) as countProductID
FROM SalesOrderDetail
LEFT JOIN Product USING (ProductID)
GROUP BY ProductID
) as a
WHERE a.countProductID = (SELECT MAX(x.countProductID) FROM
(
SELECT ProductID, COUNT(ProductID) as countProductID
FROM SalesOrderDetail
LEFT JOIN Product USING (ProductID)
GROUP BY ProductID
) as x
);
Since im using the same subquery twice. However i can't access the first one from the WHERE clause.

I guess the task is to find product or products with the maximum sales count. First you shouldn't join with PRODUCT table because all information you need is in SalesOrderDetail table. Then use LIMIT 1 to find maximum count and HAVING to select all products with maximum count:
SELECT ProductID, COUNT(ProductID) as countProductID
FROM SalesOrderDetail
GROUP BY ProductID
HAVING COUNT(ProductID) = (SELECT COUNT(ProductID) as countProductID
FROM SalesOrderDetail
GROUP BY ProductID
ORDER BY countProductID DESC
LIMIT 1 )

The final answer
SELECT ProductID, COUNT(ProductID) as countProductID
FROM SalesOrderDetail
LEFT JOIN Product USING (ProductID)
GROUP BY ProductID
ORDER BY countProductID desc
LIMIT 1

Related

SQL - get several occurences for each value with DISTINCT or GROUP BY

with DISTINCT or GROUP BY a record for each value (or set of values) can be taken like in the query below:
SELECT id, MAX(price) FROM Products GROUP BY id
The result will be something like:
ID | price
1 10
2 11
Is it possible to have, for example, 3 different prices for each ID ?
You can try below - using self join
DEMO
SELECT Products.id, Products.price,COUNT(p.price) AS rank
FROM Products
LEFT JOIN Products AS p ON Products.id = p.id AND Products.price< p.price
GROUP BY Products.id, Products.price
HAVING COUNT(p.price) < 3
ORDER BY Products.id, Products.price DESC
You can use GROUP_CONCAT if you want to get all the values, e.g.:
SELECT id, GROUP_CONCAT(price)
FROM table
GROUP BY id;
If your MySql version supports Window functions you can use RANK() and PARTITION
SELECT id, price
FROM (SELECT id, price, RANK() OVER w as price_rank
FROM test
WINDOW w as (PARTITION BY id ORDER BY price desc)) r
WHERE price_rank <= 3
ORDER BY id, price desc
One way to get the three highest prices is to use group_concat() and substring_index():
SELECT id,
SUBSTRING_INDEX(GROUP_CONCAT(price ORDER BY price DESC), ',' 3) as top3_prices
FROM Products
GROUP BY id;

How to match up dates on 2 different tables and join to an ID table?

I have a table full of product ids and their attributes. I want to join sales data and receipt data from 2 different tables and a different row for each id and date combo. So I want the output to look like this:
I tried joining the product id table and sales table to the receipt table but I'm not sure how to get the dates from the sales and receipts table to match up. Not sure of how to approach this. Thanks!
Calculate the counts for each table and combine them usung UNION ALL
select
product_id
,sales_date
-- combine the counts from both tables
,sum(sales_count)
,sum(receipt_count)
from
(
-- get the counts for the sales table
select
product_id
,sales_date
,count(*) as sales_count
-- UNION needs the same number of columns in both Select -> adding a dummy column
-- 1st Select determines the datatype
,cast(0 as int) as receipt_count
from sales
group by product_id, sales_date
UNION ALL
-- get the counts for the receipts table
select
product_id
,receipt_date
,0
,count(*)
from receipts
group by product_id, receipt_date
) as dt
group by product_id, receipt_date
select p.product_id, s.sales_date, s.sales_count, r.receipt_count
from
products p,
(select count(*) sales_count, sales_date, product_id from sales group by 2,3) s
(select count(*) receipt_count, receipt_date, product_id from receipts group by 2,3) r
where
p.product_id = s.product_id
and p.product_id = r.product_id
and s.sales_date=r.receipt_date
;

Retrieve the rows which has matches for all the rows of another resultset in mysql

The following are the tables of my application
Product(product_id(pk),name,price)
Customer(customer_id(pk),customer_name,address)
Purchases(customer_id(fk),product_id(fk),quantity);
select count(product_id),customer_id from purchases
where product_id in (
select product_id from product where price >200)
group by customer_id
i'm able to do it up to here where the above query retrieves count of the products for each customer. i even tried the below one
select sub.customer_id from (select count(product_id) as prod_count,
customer_id from purchases where product_id in
( select product_id from product where price >200)
group by customer_id) as sub
having sub.prod_count=(select count(product_id) from product where price>200);
Now how can i find the customers who purchased all the products with price above 200.
SELECT DISTINCT customer_id
FROM (
SELECT PUR.customer_id, PUR.product_id
FROM (SELECT product_id FROM Product WHERE price > 200 ) Pro_above_200 PRO
INNER JOIN Purchases PUR
ON PUR.product_id = PRO.product_id ) T
GROUP BY customer_id, product_id
HAVING COUNT(1) = (SELECT COUNT(1) FROM Product WHERE price > 200 )
Try this:
SELECT distinct customer_id from purchase
where customer_id not in
(
select customer_id
from(
select purchases.customer_id ,
case when Product.proce>200 then 1 else 0 end as price_gt_twh
from purchases
left join Producton purchases.product_id =Product.product_id
)data
WHERE price_gt_twh=0
)customers
Select * from customer join select * from product where product.price > 200.
I'm assuming you have the price column in your product table
What you need is a join statement

Mysql query to get lowest value from multiple conditions using UNION operator

I have price table with three columns:
id, price, product_id.
product_id can contain multiple prices.
I need to get lowest price product_id when query perform in mysql.
I am using multiple conditions using UNION operator in this table data is coming but results are wrong.
In this table product_id 101 has 4999 but I am getting 5000, even I have set order by price ASC
Here is my mysql fiddle link
mysql fiddle
This is very basic SQL.
select product_id, min(price) as price
from price
group by product_id;
To fetch minimum prices per product for a given range add them to case statement in group by clause:
select product_id, min(price) as price
from price
group by product_id, case when price between 100 and 5000 then 1 else 2 end;
SQL fiddle
Assuming you need the ID of each record with the min price.
Select p.* from price p
INNER JOIN (Select product_ID, Min(Price) as price from `price` group by Product_ID) sub
on sub.product_Id = p.product_Id
and sub.price = p.price
SQL FIDDLE
Otherwise...
Select product_ID, Min(Price) as price from `price` group by Product_ID
SQL FIDDLE
---- UPDATE----
Still not sure I understand the question... which is why I asked for expected output given your data. I may be able to infer the requirements which i'm not getting. As it stands I had NO idea why a union was needed, nor how this "grouping" came into play.
SELECT p.* from price p
INNER JOIN (Select product_ID, Min(Price) as price from `price` group by Product_ID) sub
on sub.product_Id = p.product_Id
and sub.price = p.price
SQL Fiddle
Assuming no overlap of product_ID in ranges...
SELECT pr.id,MIN(pr.price),pr.product_id FROM price pr WHERE pr.price >= 100 AND pr.price <= 5000 group by pr.product_id UNION SELECT pr.id,MIN(pr.price),pr.product_id FROM price pr WHERE pr.price >= 5001 AND pr.price <= 10000 group by pr.product_id

SQL - Does row match max of sums

I am getting a little tripped up with a SQL query. Here is some background.
Schema:
Product(pid, price, color),
Order(cid, pid, quantity),
Customer(cid, name, age)
I want to get the pid of the most ordered product (greatest quantity).
I have managed to determine the max value with:
Select Max(total)
From (Select Sum(quantity) as total
From Orders Group By pid) as Totals
but I am getting stuck trying to match which products are in this subquery. Here is what I have tried:
Select pid, SUM(quantity) as q
From Orders
Where q in (
Select Max(total)
From (Select Sum(quantity) as total
From Orders
Group By pid) as Totals
)
Group By pid
This says that q is an unknown column.
Any suggestions on how I could do this or do it better?
you can do a JOIN along with GROUP BY like
select p.*
from product p
join
(select pid from Order
group by pid having quantity = max(quantity)
) tab on p.pid = tab.pid;
In your posted query it's erroring q is an unknown column cause q is a column alias which you are trying to use in WHERE condition; which is not allowed.
You should be able to simply include the PID in the original query because you are grouping on it. Then ORDER BY and and get only the top result using LIMIT 1.
SELECT
pid
,Sum(quantity) as total
FROM
Orders
GROUP BY
pid
ORDER BY
Sum(quantity)
LIMIT 1
Here's one way you can do it using a subquery with limit:
select o.pid, sum(o.quantity)
from `order` o
group by o.pid
having sum(o.quantity) =
(
select sum(quantity)
from `order`
group by pid
order by sum(quantity) desc
limit 1
)
SQL Fiddle Demo
If you want only one most ordered product, then Karl's answer is fine. If you want all that have the same quantity, then:
select pid, sum(quantity) as quantity
from orders o
group by pid
having sum(quantity) = (select max(quantity)
from (select sum(quantity) as quantity
from orders o
group by pid
) q
);