Using DISTINCT, COUNT and HAVING in a MySQL Query - mysql

I want to count all players that have a sum of at least 300 points after a given date. I have this:
SELECT
COUNT(DISTINCT playerID)
FROM
table
WHERE
game_date > '$date'
HAVING
SUM(points) >= 300
Which is counting also the players that have a sum of less than 300 points. How can I solve this?

As pointed out by Andre Bossard:
To get the list of all players with points>=300:
SELECT * FROM (SELECT playerID, SUM(points) points FROM table WHERE game_date>'$date' GROUP BY playerID) a WHERE points>=300
To get the count:
SELECT COUNT(*) FROM (SELECT playerID, SUM(points) points FROM table WHERE game_date>'$date' GROUP BY playerID) a WHERE points>=300

Use a subquery for that:
SELECT COUNT(*) FROM
(
SELECT playerID, SUM(points) AS `total`
FROM `table`
WHERE game_date > '$date'
GROUP BY playerID
) tmp
WHERE total>=300

Related

Getting a win streak from a database

I have followed this tutorial on trying to get a win streak from my database of bets.
The data has a result (Win/Loss/Pending) and a date (Amongst other values)
Here is the SQL command I'm using...
SELECT *
FROM (SELECT Result,
MIN(date) as StartDate,
MAX(date) as EndDate,
COUNT(*) as Games
FROM (SELECT *,
(SELECT COUNT(*)
FROM bets G
WHERE G.result <> GR.result
AND G.date <= GR.date) as RunGroup
FROM bets GR WHERE user = 4 ORDER BY date DESC) A
GROUP BY result, RunGroup
ORDER BY Min(date)) A
WHERE result = 'Win'
ORDER BY Games DESC
The only difference with mine is I'm trying to filter a single users bets and not everyones bets but...I can see in my DB that there are 3 Win's in a row but my output is 2. Can anyone spot where I have gone wrong?
I want to get one row with the largest streak, which all I think I would need to do at this point is add LIMIT 1
Thanks
If you want all sequential wins summarized in one row, then I would suggest handling this has a gaps-and-islands problem. A simple method is to count the cumulative number of non-wins. This then assigns a group to each group of wins that can be used for aggregation:
select user, grp, count(*) as num_in_sequence,
min(date), max(date)
from (select b.*,
sum(result <> 'Win') over (partition by user order by date) as grp
from bets b
) b
where result = 'Win'
group by user, grp;
This is how I did it:
SELECT * FROM (SELECT result, MIN(date) as StartDate, MAX(date) as EndDate, COUNT(*) as Games FROM (SELECT date, result, (SELECT COUNT(*) FROM bets G WHERE G.result <> GR.result AND G.date <= GR.date AND user = ${uid}) as RunGroup FROM bets GR WHERE user = ${uid} ORDER BY date) A Where result = 'Win' GROUP BY result, RunGroup ORDER BY Min(date)) A ORDER BY Games DESC LIMIT 1

To find the maximum number of order count that occur in any 1 hour of the day from the database?

I have a food selling website in which there is order table which record the order of every user.It column for user id ,user name,orderid ,timestamp of order.I want to know the maximum number of order that has been made in any one hour span through out the day.Give me any formula for this,or any algorithm or any sql queries for these.
SQL server:
with CTE as
(
select cast(t1.timestamp as date) as o_date, datepart(hh, t1.timestamp) as o_hour, count(*) as orders
from MyTable t1
group by cast(t1.timestamp as date), datepart(hh, t1.timestamp)
)
select o_date, o_hour, orders
from CTE
where orders = (select max(orders) from CTE)
Oracle
with CTE as
(
select to_char(t1.timestamp, 'YYYYMMDD') as o_date, to_char(t1.timestamp, 'HH24') as o_hour, count(*)
from MyTable t1
group by to_char(t1.timestamp, 'YYYYMMDD'), to_char(t1.timestamp, 'HH24')
)
select o_date, o_hour, orders
from CTE
where orders = (select max(orders) from CTE)
You can get count by day and hour like this
For SQL
SELECT TOP 1
COUNT(*)
FROM myTable
GROUP BY DATEPART(day, [column_date]), DATEPART(hour, [column_date])
ORDER BY COUNT(*) DESC;
For MySQL
SELECT
COUNT(*)
FROM myTable
GROUP BY HOUR(column_date), DAY(column_date)
ORDER BY COUNT(*) DESC
LIMIT 1;

specific status on consecutive days

I have a MySQL table ATT which has EMP_ID,ATT_DATE,ATT_STATUS with ATT_STATUS with different values 1-Present,2-Absent,3-Weekly-off. I want to find out those EMP_ID's which have status 2 consecutively for 10 days in a given date range.
Please help
Please have a try with this:
SELECT EMP_ID FROM (
SELECT
IF((#prevDate!=(q.ATT_DATE - INTERVAL 1 DAY)) OR (#prevEmp!=q.EMP_ID) OR (q.ATT_STATUS != 2), #rownum:=#rownum+1, #rownum:=#rownum) AS rownumber, #prevDate:=q.ATT_DATE, #prevEmp:=q.EMP_ID, q.*
FROM (
SELECT
EMP_ID
, ATT_DATE
, ATT_STATUS
FROM
org_tb_dailyattendance, (SELECT #rownum:=0, #prevDate:='', #prevEmp:=0) vars
WHERE ATT_DATE BETWEEN '2013-01-01' AND '2013-02-15'
ORDER BY EMP_ID, ATT_DATE, ATT_STATUS
) q
) sq
GROUP BY EMP_ID, rownumber
HAVING COUNT(*) >= 10
The logic is, to first sort the table by employee id and the dates. Then introduce a rownumber which increases only if
the days are not consecutive or
the employee id is not the previous one or
the status is not 2
Then I just grouped by this rownumber and counted if there are 10 rows in each group. That should be the ones who were absent for 10 days or more.
Have you tried something like this
SELECT EMP_ID count(*) as consecutive_count min(ATT_DATE)
FROM (SELECT * FROM ATT ORDER BY EMP_ID)
GROUP BY EMP_ID, ATT_DATE
WHERE ATT_STATUS = 2
HAVING consecutive_count > 10

least value in count

i have a table employee(id,dept_id,salary,hire_date,job_id) . the following query i have to execute.
Show all the employee who were hired on the day of the week on which least no of employee were hired.
i have done the query, but am not able to get the least. please check if am correct.
select id, WEEKDAY(hire_date)+1 as days,count(WEEKDAY(hire_date)+1) as count
from test.employee group by days
This should get you the weekday on which the least number of employees were hired:
SELECT
count(id) as `Total`,
WEEKDAY(hire_date) as `DoW`
FROM
test.employee
GROUP BY `DoW`
ORDER BY `Total` DESC LIMIT 1;
select id from test.employee where hire_date in
( select count(id) count,hire_date
from test.employee
order by count desc
limit 1)
this should work
You may try this, as it will not limit to one record if you have multiple week days where the same least number of employees were hired. In reality it makes sense. The following is based on sample data.
Query:
-- find minimum id count
SELECT MIN(e.counts) INTO #min
FROM (SELECT COUNT(*) as counts,
WEEKDAY(hire_date+1) as day
FROM employee
GROUP BY WEEKDAY(hire_date+1)) e
;
-- show weekdays with minimum id counts
SELECT e2.counts as mincount,
WEEKDAY(e1.hire_date+1) as weekday
FROM employee e1
JOIN (SELECT COUNT(id) as counts,
WEEKDAY(hire_date+1) as day
FROM employee
GROUP BY day
HAVING COUNT(*) = #min) e2
ON WEEKDAY(e1.hire_date+1) = e2.day;
Results:
MINCOUNT WEEKDAY
1 6
1 3
1 4
1 2
SQLFIDDLE
select min(id), WEEKDAY(hire_date)+1 as days,count(WEEKDAY(hire_date)+1) as count
from test.employee group by days
SELECT
*
FROM
employee
WHERE
DAYOFWEEK(hire_date)
IN
(
SELECT
weekday
FROM
(
SELECT
count(*) as bcount,
DAYOFWEEK(hire_date) as weekday
FROM
employee as a
GROUP BY
weekday
HAVING
bcount = (
SELECT
MIN(tcount)
FROM
(
SELECT
count(*) as tcount,
DAYOFWEEK(hire_date) as weekday
FROM
employee
GROUP BY
weekday
) as t
)
) as q

Is it possible to get all these stats with one query?

I have a Vote-scoring system, each user can score any product each day (maximum of 10 points a day, but they can go on the same product each day).
The schema for my vote table is like so:
Vote: ID, user_id, product_id, score, date.
What I'd like to do is not only fetch the total score and amount of individual votes, (so I can work out an average) but also get the unique amount of voters (DISTINCT user_id's) in the current time frame (in this example, a month). The current query I have is:
SELECT
SUM(`Vote`.`score`) AS `score`,
COUNT(*) AS `votes`,
CONCAT(YEAR(`Vote`.`date`), '-', MONTH(Vote.date)) AS `month`
FROM
`votes` AS `Vote`
WHERE
`product_id` = 4
GROUP BY
month
ORDER BY `Vote`.`date` DESC
Thanks in advance.
Use COUNT(DISTINCT user_id) in your SELECT list.
You can also have AVG(score) calculated.
SELECT
SUM(score) AS totalScore,
COUNT(*) AS totalVotes,
COUNT(DISTINCT user_id) AS voters,
AVG(score) AS averageScore,
CONCAT(YEAR(`date`), '-', MONTH(`date`)) AS `month`
FROM
votes
WHERE
product_id = 4
GROUP BY
`month`
ORDER BY `date` DESC