SQL Having clause over filtering issue - mysql

I need to get the students who get the highest total score in the table while there are more than one student getting the highest score. Why the result is different in the following 2 queries?
SELECT * FROM
(
SELECT SUM(points) total, student_id
FROM student_score_per_subject_table
GROUP BY student_id
ORDER BY 1 DESC
) students
HAVING total = MAX(total)
The result of this query has only one return and the student_id the alphabetically smallest one;
SELECT * FROM
(
SELECT SUM(points) total, student_id
FROM student_score_per_subject_table
GROUP BY student_id
ORDER BY 1 DESC
) students
HAVING total = 100 -- highest total score
The result is desired with all highest-scorers being returned.
----- EDIT --------
MySQL version: 5.7.12

Related

SQL query to get the number of customers who purchased on multiple dates

I'm having trouble coming up with a query to get the number of customers who purchased on multiple dates.
We're given a table of product purchases. Each row in the table represents an individual user product purchase.if the customer purchased two things on the same day that does not count as an upsell as they were purchased within a similar timeframe.
'transactions' table:
column
type
id
integer
user_id
integer
created_at
datetime
product_id
integer
quantity
integer
I tried in this way
select count(*)
from
( select user_id
, count(date)
from
( SELECT user_id
, DATE(created_at) AS date
FROM transactions
GROUP BY 1,2
) S
group
by 1
having count(date)>1
) A
I think you want:
SELECT COUNT(*)
FROM
(
SELECT user_id
FROM transactions
GROUP BY user_id
HAVING COUNT(DISTINCT DATE(created_at)) > 1
) t;
The subquery finds all users having transacted on more than one date, the outer query finds the count of such users.
Count the distinct dates per user, first, then count from table when the count is > 1.
See below:
WITH T as (select user_id,
count(distinct DATE(created_at)) as count
from transactions
GROUP BY user_id)
select count(*) from T where count > 1

How to find top N records from 'group by' method where N records can contain multiple values?

I was practicing with W3 School SQL Tables. From Customers table I can select Number of Customers Per country by following SQL
select country, count(*) as NumOfCustomer
from Customers
group by country
order by NumOfCustomer Desc;
This gives me a result like this:
If I want to select top 5 countries with most customers I can not use Limit 5 because Germany and France have second most highest customers and Mexico and Spain have fifth most highest customers.Using Limit 5 won't include Mexico and Spain
How can I get a result containing all N number of highest values where highest values can be repeated for a Nth Number like before?
You could use DENSE_RANK:
Returns the rank of the current row within its partition, without gaps. Peers are considered ties and receive the same rank. This function assigns consecutive ranks to peer groups; the result is that groups of size greater than one do not produce noncontiguous rank numbers
WITH cte AS (
select country, count(*) as NumOfCustomer
from Customers
group by country
), cte2 AS (
SELECT *, DENSE_RANK() OVER(ORDER BY NumOfCustomer DESC) AS rnk
FROM cte
)
SELECT *
FROM cte2
WHERE rnk <= 5
ORDER BY NumOfCustomer DESC

Error Code: 1146. Table 'college_small.result' doesn't exist while using sql temporary tables

My sql statement is as follows:
SELECT course_id FROM (
(SELECT COUNT(course_id) AS count FROM takes GROUP BY course_id) AS result)
WHERE count IN (SELECT MAX(count) FROM result)
How can I use temporary tables twice?For example,the table "result" here.
If you simply want to obtain the course_id which has the maximum number of takes, then you can order the subquery by the count and limit the result set to one record.
SELECT course_id, COUNT(course_id) AS count
FROM takes
GROUP BY course_id
ORDER BY COUNT(course_id) DESC
LIMIT 1
If you also want to obtain all course id values, in the event that there be a tie for the maximum number of takes, then you can try the following slightly more complicated query:
SELECT result.course_id
FROM
(
SELECT course_id, COUNT(course_id) AS count
FROM takes
GROUP BY course_id
) AS result
WHERE result.count = (
SELECT COUNT(*)
FROM takes
GROUP BY course_id
ORDER BY COUNT(*) DESC
LIMIT 1
)

Sort by average rating between 2 values

I have a table called ranks which stores a 1-7 value and connects it with an item and user id. An item's rating is the average of all ratings it has been given.
Ranks table: id | userid | value | itemid.
To sort by average highest rating, I do (from an answer here):
select avg(value), itemid
from ranks
group by itemid
order by avg(value) desc
However, I also want to be able to filter items with a certain rating, not just highest rated -> lowest rated. For example, items with an average rating beteen 5 and 6.
select avg(value), itemid
from ranks
having avg(value) between 5 and 6
group by itemid
order by avg(value) desc
This gives me a nonspecific error at group by. Can anyone point me in the right direction?
Your having clause needs to come after your group by clause, so just reverse the order they appear in:
select avg(value), itemid
from ranks
group by itemid
having avg(value) between 5 and 6
order by avg(value) desc
select * from
(
select avg(value) as avgval, itemid
from ranks
group by itemid) t
where avgval between 5 and 6;
You can do it with a sub-query.
with Temp as
(
select avg(value) [rating], itemid
from ranks
)
Select * from Temp
Where rating between 5 and 6
group by itemid
order by rating desc

Count # of Similar Records, Average Count and # with specific count

I have a MySql table with a non-Unique Name Field, I'd like to query the following;
For each Name Value ("John") count how many records there are (32 records with name John), I'll end up writing this to each record.
Average the counts for each name group (e.g 32 records with John and 42 records with Sally, Average for table 37 records)
Count counts meaning e.g 6 10 Record groups, 10 20-record groups, etc
Can I do this with one or more queries?
Average for Table Groups http://sqlfiddle.com/#!2/f5af3/5:
SELECT
AVG(ct)
FROM (
SELECT
COUNT(name) as ct
FROM
names
GROUP BY
name) as temp1;
Count per count http://sqlfiddle.com/#!2/b0628/1:
SELECT
COUNT(ct) AS "Count_per_count",
ct as "Actual Count"
FROM (
SELECT
COUNT(name) as ct
FROM
names
GROUP BY
name) as temp1
GROUP BY ct;
select name, count(*) as num from table group by name;
select ((select count(*) from table) / (select count(distinct name) from table));
select count(*) as num, type from
(select count(*) as type from table group by name) t
group by type