Count unique values from duplicates - mysql

I have following data on the table.
Uid | comm | status
-------------------
12 23 eve
15 23 eve
20 23 mon
12 23 mon
20 23 eve
17 23 mon
how do i query to get below result to avoid duplicates and make sure if i count uid for "eve" and same uid appears on "mon" then count only uid for "eve"?
count | status
-------------------
3 eve
1 mon
Thanks for the help!

You can use the following query in order to pick each Uid value once:
SELECT Uid, MIN(status)
FROM mytable
GROUP BY Uid
Output:
Uid MIN(status)
---------------
12 eve
15 eve
17 mon
20 eve
Using the above query you can get at the desired result like this:
SELECT status, count(*)
from (
SELECT Uid, MIN(status) AS status
FROM mytable
GROUP BY Uid ) AS t
GROUP BY status
Demo here

Related

SQL COUNT giving same value

I have a table that looks like this...
Attendance_ID person_ID Meeting_ID date
--------------- --------- ---------- ----------
23 25 123 2013-03-21
24 25 456 2013-03-21
25 25 789 2013-03-21
26 13 147 2013-03-21
27 25 123 2013-03-22
28 82 147 2013-03-22
29 82 456 2013-03-22
30 13 147 2013-03-23
31 25 456 2013-03-23
32 13 456 2013-03-24
33 25 456 2013-03-28
The goal is to print out all the the times a employee has missed one or more meetings during the day. I have tried the following query but it gives me the same result of 2 for all dates...
SELECT
replace(replace(dayname(date),"Saturday", "Weekend"),"Sunday", "Weekend") AS day,
count(distinct personID) AS absences
from
AttendanceRecord
GROUP BY
day;
where it should be...
Friday 2
Thursday 3
Weekend 3
Where am I going wrong? Any help would be welcome as my SQL skills are a bit rusty. Thanks!
This is MySQL, and the table above is the dates of absences. So if the emplyee missed meeting 123, they would show up on this table. The query is to see the number of employees who missed a meeting on that day.
count(distinct personID) AS absences
should be
count(distinct employeeID) AS absences
because if you see your example data you have:
Employee ID person ID Meeting ID date
----------- --------- ---------- ----------
23 25 123 2013-03-21
24 25 456 2013-03-21
25 25 789 2013-03-21
where these 3 different Employees have the same Person ID
Either that, or you're already getting the correct values; there are 10 different EmployeeID but there are fewer than that PersonID
If you still want to count repeated personIDs, then change
count(distinct personID) AS absences
to
count(personID) AS absences
Could be, as long as every meeting was attended by at least one person.
WITH ALL_MEETING_EMPLOYEE_COMBOS AS
( SELECT EmployeeID,
Meeting_ID,
date
FROM (SELECT DISTINCT
Employee_ID
FROM Attendance_Record
)
CROSS JOIN
( SELECT DISTINCT
meeting_id,
date
FROM attendance_record
)
)
SELECT Employee_ID,
Date,
COUNT(1) AS MissedOnThisDayCount
FROM ALL_MEETING_EMPLOYEE_COMBOS T1
WHERE NOT EXISTS
( SELECT 1
FROM ATTENDANCE_RECORD AR
WHERE T1.employee_id = AR.employee_id
AND T1.meeting_id = AR.meeting_id
)
GROUP BY employee_id, date

MySQL get the latest products with distinct product_name from a particular month

I've the following product table in my database. I want to get the rows of all the products with distinct product_name added in the month of Dec in the descending order of their id.
id product_name qty month
1 Apple 20 Dec
2 Banana 40 Jan
3 Cherry 60 Jun
4 Apple 25 Dec
5 Banana 50 Dec
6 Papaya 20 Dec
7 Guava 34 Aug
8 Watermelon 55 Mar
9 Apple 75 Dec
10 Orange 32 Dec
The resulting table should be as below:
id product_name qty month
10 Orange 32 Dec
9 Apple 75 Dec
6 Papaya 20 Dec
5 Banana 50 Dec
So far I've come up with the following query and it doesn't get the result I need.
SELECT *
FROM product
WHERE month = "Dec"
GROUP BY product_name
ORDER BY id DESC
The problem with this query is that it gets the first row/record of Apple rather than last one as shown in table below:
id product_name qty month
10 Orange 32 Dec
6 Papaya 20 Dec
5 Banana 50 Dec
1 Apple 20 Dec
Can anyone help me write a proper mysql query for this?
You can use the following query:
SELECT MAX(id), product_name
FROM product
WHERE month = "Dec"
GROUP BY product_name
to get the biggest id per product_name:
Output:
max_id product_name
9 Apple
5 Banana
10 Orange
6 Papaya
Using the above query as a derived table you can join back to the original table in order to get the rest of the fields:
SELECT t1.*
FROM product AS t1
INNER JOIN (
SELECT MAX(id) AS max_id, product_name
FROM product
WHERE month = "Dec"
GROUP BY product_name
) AS t2 ON t1.id = t2.max_id and t1.product_name = t2.product_name
ORDER BY t1.id
Demo here

DISTINCT with GROUP BY in MySQL

If I'm selecting distinct values, but then I group the results, are the values only distinct within each grouping, or across all groupings?
For example:
month | id
|
01 | 17
01 | 17
01 | 19
04 | 17
04 | 20
If I run
select month, count(distinct id)
from table
group by month
What counts will I get for the two months?
You would get 2 for each month.
Here is a SQL Fiddle showing the results.

Mysql: find active users who logged in once a week

I have a table users and another table logins everytime the user log-in into the website we record a row in logins ex.
Users
-----
14 | name1
17 | name2
20 | name3
21 | name4
25 | name5
logins
----
14 | 2015-03-01
14 | 2015-03-07
14 | 2015-03-16
14 | 2015-03-24
14 | 2015-03-30
17 | 2015-03-01
17 | 2015-03-07
17 | 2015-03-16
17 | 2015-03-17
17 | 2015-03-30
20 | 2015-03-01
20 | 2015-03-07
20 | 2015-03-08
20 | 2015-03-16
20 | 2015-03-25
20 | 2015-03-30
if start date is 2015-03-01 and end date is 2015-04-01 then 14 & 20 should be selected while 17 wont be selected since he didn't login in the week of 03-22 to 03-28 so the result would be
Result
------
2
First you get the list of users per week which has logged in at least once, then you count per month the amount of users:
SELECT LoginYear,LoginWeek,COUNT(*) as NumbUsers
FROM (
SELECT Year(logins.date) as LoginYear, Week(logins.date) as LoginWeek, logins.UserID
FROM logins
WHERE logins.date>='2015-03-01'
GROUP BY LoginYear, LoginWeek, logins.UserID
HAVING COUNT(*)>0
) t
GROUP BY LoginYear,LoginWeek;
Week numbering: MySQL can count the weeks in different ways (such as starting on a Sunday/Monday) using the mode: WEEK(date,mode). See the WEEK MySQL documentation.
Update: to get the number of persons which has been logged in at least once every week: first we get the users that were logged in at least once per week in the subquery weektable. Then the users are select which have a week count which equals the total number of weeks in that period (thus having been online each week). Finally we count those users.
SELECT COUNT(*)
FROM (
SELECT UserID
FROM (
SELECT Year(logins.date) as LoginYear, Week(logins.date) as LoginWeek, logins.UserID
FROM logins
WHERE logins.date>='2015-03-01'
GROUP BY LoginYear, LoginWeek, logins.UserID
HAVING COUNT(*)>0
) weektable
GROUP BY UserID
HAVING COUNT(*)>=TIMESTAMPDIFF(WEEK,'2015-03-01',NOW())
) subq;
Note 1: I put the date '2015-03-01' as an example but you can change this or put as a variable.
Note 2: depending on the dates you choose it can be that the week count by TIMESTAMPDIFF is less than the maximum number of weeks (counted by COUNT(*)), since it does not count half weeks. Therefore I put >= in the last line: HAVING COUNT(*)>=TIMESTAMPDIFF(WEEK,'2015-03-01',NOW()).
I cannot test it here at the moment but something like
SELECT COUNT(Users.id) WHERE logins.date>=XXXX AND logins.date<=XXXX GROUP BY Users.id
should work

Select up to x rows of each group

With a table of:
id | name | job | rank
01 john teacher 4
02 mark teacher 2
03 phil plummer 1
04 dave teacher 7
05 jim plummer 9
06 bill plummer 2
How can I select up to 2 rows of each job (if possible sorted by rank ASC in each group, so that the lowest two ranking of each group get picked). The result I'd be looking for is:
02 mark teacher 2
01 john teacher 4
03 phil plummer 1
06 bill plummer 2
This basically groups by job, with a limit to 2 and sorted by rank. I've been trying with GROUP BY as well as LEFT JOIN, but I just can't figure out how to do this. When creating a "temporary list" of jobs with GROUPING BY job, how do I join more than once onto that job?
SELECT id, name, job, rank
FROM TableName a
WHERE
(
SELECT COUNT(*)
FROM TableName as f
WHERE f.job = a.job AND
f.rank <= a.rank
) <= 2;
SQLFiddle Demo