SQL COUNT giving same value - mysql

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

Related

Count unique values from duplicates

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

MYSQL Stuck Generating temp table (massive query)

I have 4 tables (1 to many):
Dont say anything about that "email" relation. It is how my developer boss built it years ago.
EMPLOYEES (+-50 results)
------------------------------------------------
id name
1 EmpName 1
2 EmpName 2
CUSTOMERS (+50k results)
------------------------------------------------
id name email employee_assigned
1 John john#doe.com 12
2 Donald donald#duck.com 6
INTERESTS_CATEGORIES (+650k results)
------------------------------------------------
id customer_email category_id
1 john#doe.com 97
2 john#doe.com 13
3 donald#duck.com 56
4 donald#duck.com 126
5 donald#duck.com 45
INTERESTS_PRODUCTS (+650k results)
------------------------------------------------
id customer_email product_id
1 john#doe.com 78
2 john#doe.com 23
3 donald#duck.com 19
4 donald#duck.com 56
5 donald#duck.com 45
So I need to filter the customers by their assigned employee and their interests.
And here is the query:
SELECT
*
FROM
(
SELECT
customers.id AS 'id',
customers.name AS 'first_name',
customers.email,
employees.id AS 'employee_id'
FROM
customers,
employees
WHERE
employees.id = 2
AND
customers.employee_assigned = employees.id
) AS myCustomers
LEFT JOIN interests_categories
ON interests_categories.customer_email = myCustomers.email
LEFT JOIN interests_products
ON interests_categories.customer_email = myCustomers.email
WHERE
(
interests_categories.category_id = 20
OR
interests_categories.category_id = 21
)
GROUP BY myCustomers.email
So, the problem:
If the employee has a low number of assigned customers (like 3) query
is successfull.
If the employee has a medium-high number of assigned customers (over 100) query stucks.
I execute SHOW PROCESSLIST and it is stucked "Generating temp table".
Anyone has idea? :(
Thank you.
Check the indexes on your tables and try this:
SELECT
c.id AS 'id',
c.name AS 'first_name',
c.email,
e.id AS 'employee_id'
ic.*,
ip.*
FROM customers c
JOIN employees e
ON c.employee_assigned = e.id
LEFT JOIN interests_categories ic
ON ic.customer_email = c.email
LEFT JOIN interests_products ip
ON ic.customer_email = c.email
WHERE
(
ic.category_id IN (20,21)
AND e.id = 2
)
GROUP BY myCustomers.email
Incidentally, a less dumb design might look like as follows. If it was me, I'd start with this, and provide properly representative CREATE and INSERT statements accordingly. Also, I'm curious about where category_id comes from - because that's potentially an area for further optimization.
EMPLOYEES
------------------------------------------------
employee_id name
6 EmpName 1
12 EmpName 2
CUSTOMERS
------------------------------------------------
customer_id name email employee_assigned
1 John john#doe.com 12
2 Donald donald#duck.com 6
INTERESTS_CATEGORIES
------------------------------------------------
customer_id category_id
1 97
1 13
2 56
2 126
2 45
INTERESTS_PRODUCTS
------------------------------------------------
customer_id product_id
1 78
1 23
2 19
2 56
2 45

How to get RUNNING TOTAL for DATES- ORDER dates in ASC RANK

Imagine you have a members with distinct member_ids and dates of service
you now need to order the dates of service in ascending order and return the order of these dates in another column (date_count). the final result will look like this:
memberid name date date_count
122 matt 2/8/12 1
122 matt 3/9/13 2
122 matt 5/2/14 3
120 luke 11/15/11 1
120 luke 12/28/14 2
100 john 1/12/10 1
100 john 3/2/12 2
100 john 5/30/12 3
150 ore 5/8/14 1
150 ore 9/9/14 2
here is the query that works but does not return the date_count in ranking (1,2,3) order. This instead returns the same number for date_count, not sure why the num
memberid name date_count
122 matt 3
122 matt 3
122 matt 3
120 luke 5
120 luke 5
120 luke 5
100 john 6
100 john 6
150 ore 2
150 ore 2
SELECT A.MEMBERID, A.NAME,A.DATE, COUNT(B.DATE) AS DATE_COUNT FROM #WCV_COUNTS A
INNER JOIN #WCV_COUNTS B
ON A.MEMBERID <= B.MEMBERID
AND A.MEMBERID= B.MEMBERID
GROUP BY A.MEMBERID, A.NAME, A.DATE
ORDER BY A.MEMBERID
Thanks for help in advance!
Use ROW_NUMBER()
SELECT memberid, name, date,
ROW_NUMBER() OVER (PARTITION BY memberid ORDER BY date) AS date_count
FROM #WCV_COUNTS
ORDER BY memberid, date

Improve sql query in MySQL in PHPMYADMIN

I have this query:
SELECT `jos_eb_registrants`. * , `jos_eb_field_values`. *
FROM jos_eb_registrants, jos_eb_field_values
WHERE `jos_eb_registrants`.`event_id` =3
AND `jos_eb_registrants`.`id` = `jos_eb_field_values`.`registrant_id`
It returns me everything from these two tables, but gives me rows with duplicate names, because ONE name from first table can have more than one field value. How to make field values not in separate rows, but in one row near one name, without duplicates. Please edit this query with my variables.Tables connected via Id and registrant_id.
jos_eb_field_values
1 id
2 registrant_id
3 field_id
4 field_value
jos_eb_registrants
1 id
2 event_id
3 user_id
4 group_id
5 first_name
6 last_name
7 organization
8 address
9 address2
10 city
11 state
12 country
13 zip
14 phone
15 fax
16 email
17 number_registrants
18 total_amount
19 discount_amount
20 amount
21 register_date
22 payment_date
23 payment_method
24 transaction_id
25 comment text
26 published
27 cart_id int(11)
28 deposit_amount
29 payment_status
30 coupon_id
31 check_coupon
32 tax_amount
33 registration_code
34 is_reminder_sent
35 is_group_billing
Try this:
SELECT DISTINCT jos_eb_registrants. * , jos_eb_field_values. *
FROM jos_eb_registrants
INNER JOIN jos_eb_field_values ON jos_eb_registrants.id = jos_eb_field_values.registrant_id
WHERE jos_eb_registrants.event_id =3

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