Joining two tables and find 10 maximum averages - mysql

I am developing a business review system.
business table is-
id category
1 1
2 1
3 1
4 2
review table is -
id bid reviewer_point
1 1 4
2 1 3
3 2 4
4 2 5
I need to return the 10 business ID's of the top rated (based on rating point average) business.
So far i could find the average of the rating of each business.
SELECT COUNT(reviewer_point) AS COUNT, AVG(reviewer_point) AS average FROM reviews WHERE bid = 1
How can i get my preferred solution. Thanks in advance

Just order by the average descending and use a LIMIT clause
SELECT bid, AVG(reviewer_point) AS average
FROM reviews
GROUP BY bid
ORDER BY average DESC
LIMIT 10
EDIT - If you want to only do this for a specific category:-
SELECT reviews.bid, AVG(reviews.reviewer_point) AS average
FROM reviews
INNER JOIN categories
ON reviews.bid = categories.id
WHERE categories.category = 1
GROUP BY reviews.bid
ORDER BY average DESC
LIMIT 10

It doesn't seem like category is needed in your solution, unless I'm missing something.
Its going to be something like:
SELECT bid, COUNT(*) as review_count, AVG(reviewer_point) as average_points
FROM reviews
GROUP BY bid
ORDER BY average_points DESC
LIMIT 10;

Related

Select most searched keyword from MySql group by q and user_id

I want to show most searched keyword in my website. my search log table is this:
id
user_id
q
1
1
shoes
2
2
cover
3
1
phone
4
3
shoes
5
3
shoes
6
3
cover
7
4
shoes
I write this query to get unique search q and show them sort by repeat time:
SELECT `q`, COUNT(`q`) AS `value_occurrence` FROM search_queries GROUP BY q ORDER BY `value_occurrence` DESC
but there is an issue, if some one search shoes for 10 time, my query's value_occurrence increase 10, but i want just count any keyword for any single user_id just one time.
i try this but it's not correct way:
GROUP BY q,user_id
You must count the distinct user_ids:
SELECT q, COUNT(DISTINCT user_id) AS value_occurrence
FROM search_queries
GROUP BY q
ORDER BY value_occurrence DESC

Find customers with similar tastes while excluding certain customers

I have a table documenting purchases from customers, with one row per purchase:
CustomerID | ProductID
1 | 1000
1 | 2000
1 | 3000
2 | 1000
3 | 1000
3 | 3000
... | ...
I am using the following code to find the ten customers with the greatest number of overlapping products with customer #1 (first result is the one with the most overlap etc):
SELECT othercustomers.CustomerID, COUNT(DISTINCT othercustomers.ProductID)
FROM `purchases` AS thiscustomer
JOIN `purchases` AS othercustomers ON
thiscustomer.CustomerID != othercustomers.CustomerID
AND thiscustomer.ProductID = othercustomers.ProductID
WHERE thiscustomer.CustomerID = '1'
GROUP BY othercustomers.CustomerID
ORDER BY COUNT(DISTINCT othercustomers.ProductID) DESC
LIMIT 10
The code yields the expected output (Customer ID + total number of overlapping products with customer #1).
I would now like the query to exclude customers with overlapping purchases who have purchased more than 1000 different products, because these are bulk buyers who purchase the entire stock and whose purchase history therefore has no meaning when searching for customers with a similar taste.
In other words, if customer #500 had bought >1000 different products, I want him/her excluded from the results when searching for customers with a similar taste to that of customer #1 - even if customer #500 has bought all three products that customer #1 had bought and would ordinarily rank first in similarity/overlap.
I suppose some HAVING is in order, but I cannot seem to figure out what the appropriate condition is.
Thanks!
I think that HAVING won't do what you want, since it will only give you the total count of overlaping products, while you want the total count of products for the other customer.
You could filter with a correlated subquery in the WHERE clause:
SELECT othercustomers.CustomerID, COUNT(DISTINCT othercustomers.ProductID)
FROM `purchases` AS thiscustomer
JOIN `purchases` AS othercustomers ON
thiscustomer.CustomerID != othercustomers.CustomerID
AND thiscustomer.ProductID = othercustomers.ProductID
WHERE
thiscustomer.CustomerID = '1'
AND (
SELECT COUNT(DISTINCT ProductID)
FROM `purchases` AS p
WHERE p.CustomerID = othercustomers.CustomerID
) < 1000
GROUP BY othercustomers.CustomerID
ORDER BY COUNT(DISTINCT othercustomers.ProductID) DESC
LIMIT 10
For performance, you want an index on purchases(CustomerID, ProductID).

Joining table in mysql

I am developing a business review system.
business table is-
id category
1 1
2 1
3 1
4 2
review table is -
id bid reviewer_point
1 1 4
2 1 3
3 2 4
4 2 5
I need to return the 10 business ID's of the top rated (based on rating point average) business filtered by category.
So far i could find the average of the rating of each business.
SELECT business.category, bid,
COUNT(*) AS review_count, AVG(reviewer_point) AS average_points
FROM reviews
GROUP BY bid
ORDER BY average_points DESC WHERE category = 1 LIMIT 10;
I am unable to use WHERE clause. How can i get my preferred solution. Thanks in advance
The order in a mysql single query is:
1st SELECT;
2nd FROM;
3rd WHERE;
4th GROUP BY;
5th HAVING;
6th ORDER BY;
7th LIMIT.
Try put each with a break line.
The WHERE clause has to come before the GROUP BY
SELECT business.category, bid,
COUNT(*) AS review_count, AVG(reviewer_point) AS average_points
FROM review
WHERE category = 1
GROUP BY bid
ORDER BY average_points DESC
LIMIT 10;
However, this still won't work as the business table hasn't been joined in this query. I'd include this but there's no obvious way to join business to review. Should the review table have a column containing a reference to business.id?
SQLFiddle here
Best of luck.
EDIT
With the information supplied in a comment (below) by OP the revised query becomes
SELECT b.category, r.bid,
COUNT(*) AS review_count, AVG(reviewer_point) AS average_points
FROM review r
INNER JOIN business b
ON b.id = r.bid
WHERE b.category = 1
GROUP BY r.bid, b.category
ORDER BY average_points DESC
LIMIT 10;
and the updated SQLFiddle can be found here

MySQL First GROUP BY, then ORDER

I've been searching all over, but couldn't come up with a proper solution to sort my table 'shop'.
This is how it looks:
Product Price
---------------------------------
Site 1 35
Site 2 50
Site 3 15
Site 1 30
Site 2 5
Now I need it to look like this:
Product Price
---------------------------------
Site 2 50
Site 2 5
Site 1 35
Site 1 30
Site 3 15
The table should be sorted starting with the highest price and then grouping it by the product.
I tried a million different queries and the closest I got was this:
SELECT m.* FROM shop m
INNER JOIN
(SELECT product, MAX(price) AS maxprice FROM shop GROUP BY product ORDER BY maxprice ASC) s
ON m.product = s.product
ORDER BY s.maxprice DESC
The query does it's job but sorts the prices in the group the wrong way around.
Product Price
---------------------------------
Site 2 5
Site 2 50
Site 1 30
Site 1 35
Site 3 15
What am I doing wrong? Help is much appreciated!
Best and thanks a million!
Select x.product, x.price from
(Select product, max(price) as mprice from shop
group by product) as tbl inner join shop x on tbl.product = x.product
order by tbl.mprice desc, x.Price desc
I also notice you created a fiddle would have saved me some time but here is the update fiddle
SELECT s.product, s.Price
from (Select product, max(price) as mprice
from shop group by product) as tbl
inner join shop s on s.product = tbl.product
order by tbl.mprice desc, s.price desc
http://sqlfiddle.com/#!2/c5eb64/3
You've got two levels of sorting, so you need to describe both in your ORDER BY
ORDER BY s.maxprice DESC, m.price DESC

MySQL check if MAX value has duplicates

I'm running contests on my website. Every contest could have multiple entries. I want to retrieve if only the MAX value of votes has a duplicate.
The table is as follows:
contest_id entry_id votes
1 1 50
1 2 34
1 3 50
2 4 20
2 5 55
3 6 53
I just need the query to show me that contest 1 has a duplicate MAX value without additional information.
I tried this but didn't work:
SELECT MAX(votes) from contest group by contest_id having count(votes) > 1
SELECT a.contest_ID
FROM contest a
INNER JOIN
(
SELECT contest_id, MAX(votes) totalVotes
FROM contest
GROUP BY contest_id
) b ON a.contest_ID = b.contest_ID AND
a.votes = b.totalvotes
GROUP BY a.contest_ID
HAVING COUNT(*) >= 2
SQLFiddle Demo
This finds the max votes value per contest and counts the entries with that number of votes.
It then displays contest with more than one hit.
SELECT contest_id
FROM contests
WHERE votes=(
SELECT MAX(votes) FROM contests c WHERE c.contest_id=contests.contest_id
)
GROUP BY contest_id
HAVING COUNT(*) > 1;
SQLfiddle for testing.
You could do it by first selecting the maximum number of votes for each contest ID in a subquery, and then joining against the results (demo on SQLFiddle):
SELECT contest_id, votes
FROM contest
JOIN (
SELECT contest_id, MAX(votes) AS votes
FROM contest GROUP BY contest_id
) AS foo USING (contest_id, votes)
GROUP BY contest_id
HAVING COUNT(*) > 1
The nice thing about doing it like this is that it's an independent subquery, so MySQL only needs to rub it once.
Ps. Yes, this is basically identical to JW's answer, but I figured I'd leave it up anyway to show the slightly different syntax I used for the join.