Getting all accounts with at least 3 projects, and joining account details - mysql

I'm using this query to get all the accounts with at least 3 projects.
SELECT
accounts.id,
accounts.name,
COUNT(accounts_project_1project_idb) as count
FROM accounts_project_1_c
LEFT JOIN accounts ON accounts_project_1accounts_ida = accounts.id
LEFT JOIN project ON accounts_project_1project_idb = project.id
LEFT JOIN project_cstm ON id_c = project.id
GROUP BY accounts_project_1accounts_ida
HAVING COUNT(accounts_project_1project_idb) >= 3
ORDER BY count DESC
Where accounts is the account table, project the project one, and project_cstm a table containing more information about projects
This request returns me 153 results.
But now, I would like to get the contact linked to an account. If it exists several contacts, I don't really care, I just want one.
SELECT
accounts.id,
accounts.name,
contacts.first_name,
contacts.last_name,
contacts.phone_mobile,
contacts.phone_work,
COUNT(accounts_project_1project_idb) as count
FROM accounts_project_1_c
LEFT JOIN accounts ON accounts_project_1accounts_ida = accounts.id
LEFT JOIN project ON accounts_project_1project_idb = project.id
LEFT JOIN project_cstm ON id_c = project.id
LEFT JOIN accounts_contacts ON accounts.id = accounts_contacts.account_id
LEFT JOIN contacts ON accounts_contacts.contact_id = contacts.id
GROUP BY accounts_project_1accounts_ida
HAVING COUNT(accounts_project_1project_idb) >= 3
ORDER BY count DESC
This request returns 173 results.
I don't really get it, using left join it should not add any row right?
Can you tell me what I'm doing wrong?
Thanks a lot.

I think you want the HAVING to be:
HAVING COUNT(DISTINCT accounts_project_1project_idb) >= 3
You probably want that in the SELECT as well.

Related

MYSQL count group by with a left join where there is an entry in a third table

I have a table of groups with details of groups that my users can join and a separate table of group members to show which users have joined which groups. The group_members table just has a column for group_id and a column for user_id. If there is a row with group_id = 3 AND user_id = 10 then we know user 10 is a member of group 3.
I have the following mysql statement that works well to return the details of the groups including the number of members each group has depending upon a couple of conditions in the WHERE clause.
SELECT groups.*, COUNT(group_members.group_id) AS member_count
FROM groups LEFT JOIN
group_members
ON groups.group_id = group_members.group_id
WHERE groups.deleted = 0 AND
groups.trainer_id = ' .$trainer_id .'
GROUP BY groups.group_id
ORDER BY groups.group_name'
The problem is though that users can be deleted in and aren't always removed from the group_members table when this happens. This means that users can show up in the count even though they are no longer actually in the system in a third users table.
So I want to only include group members in the count if they are also present in the users table. I thought I could do this with an INNER JOIN between the group members and users tables. Something like this...
SELECT groups.*, COUNT(users.user_id) AS client_count
FROM groups LEFT JOIN
group_members
ON groups.group_id = group_members.group_id INNER JOIN
users
ON group_members.user_id = users.user_id
WHERE groups.deleted = 0 AND groups.trainer_id = ' .$trainer_id .'
GROUP BY groups.group_id
ORDER BY groups.group_name
The trouble with this is that when a group has no members the group is not showing up in the results. I guess because it is not able to join to the users table.
If anyone could explain to me how I can achieve what I am looking to do I'd be very grateful.
A LEFT JOIN to users` should really fix your problem:
SELECT g.*, COUNT(u.user_id) AS client_count
FROM groups g LEFT JOIN
group_members gm
ON g.group_id = gm.group_id LEFT JOIN
users u
ON gm.user_id = u.user_id
WHERE g.deleted = 0 AND g.trainer_id = ' .$trainer_id .'
GROUP BY g.group_id
ORDER BY g.group_name;
If a group is not being returned, then it does not meet the WHERE filtering conditions. All groups meeting those conditions should be returned if LEFT JOIN is used for both joins.
I would also strongly advise you to use parameters rather than munging query strings, when you call queries from an application language.
You can just do a LEFT JOIN instead of INNER on the users table. The COUNT function skips null entries so your last query should work.

I want to improve my search performance mysql

I want to improve my search performance. I want to search the user against the services and specialty. user in listed as per the filter applied either by specialty or by services or can be both.There are 5 tables i want to get the data from all the table
I have below table structure
1) users :- id ,first_name,last_name
2) users_services :- id ,user_id,service_id
3) users_speciality :- id,user_id,specility_id
4) mst_services :- id,name
5) mst_speciality :- id,name
I have used this query to get the result and it works fine.
select u.id,first_name,last_name,location,services.name as service_name,speciality.name as specility_name from users as u
inner join users_services on u.id =users_services.user_id
Inner join mst_services as services on services.id=users_services.service_id
inner join users_speciality on u.id =users_speciality.user_id
Inner join mst_speciality as speciality on speciality.id=users_speciality.service_id WHERE speciality.name ="specificity one"
as per the normalization it seems correct.But when data is more than 1,00,000 that time joining too many table causes may create problem.
what should i do for filter the user according to services and specialty ?
Have you tried like this ?
SELECT users.id,first_name,last_name, mst_services.name as service, mst_speciality.name AS speciality
FROM users
LEFT JOIN users_services ON users.id = users_services.user_id
LEFT JOIN users_speciality ON users.id = users_speciality.user_id
LEFT JOIN mst_services ON service_id = mst_services.id
LEFT JOIN mst_speciality ON speciality_id = mst_speciality.id
WHERE users.id IN
(SELECT user_id FROM users_services
WHERE service_id = (SELECT id FROM mst_services WHERE name = "service one")
UNION ALL
SELECT user_id FROM users_speciality
WHERE speciality_id = (SELECT id FROM mst_speciality WHERE name = "spercial one"))
ORDER BY first_name,last_name,service,speciality

MySQL - join two tables, group and count

I have two tables:
reviewStatusPhases - id|name
and
userPhase - id|reviewStatusPhase_id|user_id|created_at|updated_at
The reviewStatusPhases table have records inserted (Active, Inactive, On Pause, Terminated...), and userPhase is empty.
The tables are connected via
userPhase.reviewStatusPhase_id = reviewStatusPhases.id
one to one.
Is it possible that in one query I get all reviewStatusPhases, and cound how many users are in each phase? In this case I will get something like this:
Active (0 Users)
Inactive (0 Users)
On Pause (0 Users)
Terminated (0 Users)
I'm making some assumptions here (e.g. INNER JOIN versus LEFT JOIN in the join, and DISTINCT in the count), but it sounds like you just want
SELECT reviewStatusPhases.name, COUNT(DISTINCT userPhase.user_id)
FROM userPhase INNER JOIN reviewStatusPhases
ON userPhase.reviewStatusPhase_id = reviewStatusPhases.id
GROUP BY reviewStatusPhases.name
Query will be as follows:
SELECT r.name as `name`, count(u.id) as `count` FROM reviewStatusPhases r LEFT OUTER JOIN userPhase u ON r.id = u.reviewStatusPhase_id GROUP BY r.name
left outer join with reviewStatusPhases on left to show all names.
group by names of reviewStatusPhases.
display reviewStatusPhases name and count of user id's (to neglect null values)
Use LEFT JOIN as follows:
SELECT COUNT(m.UserId) FROM Table1 m
LEFT JOIN Table2 k ON k.StatusId = m.StatusId
WHERE k.Status = 'Inactive'
You can easily use the Status column to track the users and their activities. In your case, ReviewStatus.
I hope the following will be helpful
SELECT RPS.Name, COUNT(UP.user_id)
FROM reviewStatusPhases RPS
LEFT OUTER JOIN userphases UP ON RPS.id = UP.reviewStatusPhase_id
GROUP BY RPS.Name
ORDER BY RPS.Name
SELECT
DISTINCT s.s_level AS 'Level',
COUNT(DISTINCT s.s_id) AS Schools,
COUNT(DISTINCT st.st_id) AS Teachers
FROM schools AS s
JOIN school_teachers AS st ON st.st_school_idFk = s.s_id AND st.st_status = 1
WHERE s.s_status = 1
GROUP BY s.s_level

MySQL not the expected output - YEAR() won't work

I have a problem with a query which dosen't output what I expects and I cant get it to work.
The query is
SELECT COUNT(event_type_id), userprofiles.id as userprofile_id, users.first_name, users.last_name
FROM users, userprofiles
LEFT JOIN event_matches ON event_matches.userprofile_id = userprofiles.id
AND event_type_id = 1
LEFT JOIN activities ON activities.id = event_matches.activity_id
AND YEAR(activities.start) = 2012
WHERE userprofiles.home_id = 2
AND users.id = userprofiles.user_id
GROUP BY userprofiles.id
ORDER BY COUNT(event_type_id) DESC
But when I run this query it gets all the activities and not only the ones from 2012, it seems like the LEFT JOIN does something. If i dont use LEFT JOIN and instead use JOIN, the query works, but then I only get the user who has a event_type_id = 1 in 2012. But the reason why I used the LEFT JOIN is because I want to have alle the users, and not only the ones who has a event_type_id.
Hopes someone can see my mistake and help me.
So what -- in English are you trying to get... Ex: For all user profiles where home_id = 2, how many events of type 1 were within 2012. By doing left joins, you are saying I want all profiles of Home_ID = 2 regardless of attending an event of type 1. You would want to change them from LEFT JOINs to just JOIN (INNER JOIN) if that is the case
This is for all user profiles regardless of an actual event that was of type 1 within 2012, this only cares if it finds an event of type 1
SELECT
COUNT(event_type_id),
userprofiles.id as userprofile_id,
users.first_name,
users.last_name
FROM
userprofiles
JOIN users
ON userprofiles.user_id = users.id
LEFT JOIN event_matches
ON userprofiles.id = event_matches.userprofile_id
AND event_matches.event_type_id = 1
LEFT JOIN activities
ON event_matches.activity_id = activities.id
AND YEAR(activities.start) = 2012
WHERE
userprofiles.home_id = 2
GROUP BY
userprofiles.id
ORDER BY
COUNT(event_type_id) DESC
by changing to the granular activity table, you would get your count of event types = 1 AND the year was of 2012
SELECT
COUNT(activities.id),
... rest of query...
ORDER BY
COUNT(activities.id) DESC
If you only want those profiles that actually HAD events of type 1 in the year 2012, change to JOIN
SELECT
COUNT(event_type_id),
userprofiles.id as userprofile_id,
users.first_name,
users.last_name
FROM
userprofiles
JOIN users
ON userprofiles.user_id = users.id
JOIN event_matches
ON userprofiles.id = event_matches.userprofile_id
AND event_matches.event_type_id = 1
JOIN activities
ON event_matches.activity_id = activities.id
AND YEAR(activities.start) = 2012
WHERE
userprofiles.home_id = 2
GROUP BY
userprofiles.id
ORDER BY
COUNT(event_type_id) DESC

MySQL select count with join

I am trying to get a list of data from multiple tables in a view for analytics - most of the data comes from one table and then I need to get the counts from multiple other tables to show number of logins, number of users and so on.
I am using the below query (simplified to show only some rows and one join):
Select
companies.company_name, companies.last_login, companies.last_ip,
(SELECT COUNT(*) FROM auditing_master GROUP BY company_id) AS audit_count
From
companies
Left Join
auditing_master On auditing_master.company_id = companies.id
Group by
companies.id
When I run this I get an error:
#2014 - Commands out of sync; you can't run this command now
If I run it without the GROUP BY in the SELECT COUNT (*) then it doesn't give any error but it returns a count of all entries in the auditing_master table regardless of which company it refers to.
How can I get a single query to show me the required data from the companies table whilst also showing a total from auditing master (and others) grouped by the company ID?
Edit
Code when using multiple count/joins:
Select
c.company_name, c.last_login, c.last_ip,
COUNT(am.company_id) AS audit_count,
COUNT(u.company_id) AS users,
COUNT(e.company_id) AS employees
From
companies c
Left Join
auditing_master am On am.company_id = c.id
Left Join
users u On u.company_id = c.id
Left Join
employees e On e.company_id = c.id
Group by
c.id
This query locally in PHPMyAdmin on WAMP with only around 10 companies takes 7 seconds to complete and give "meanngless" results that don't correlate to anything.
Thanks
Inner queries in the SELECT clause must return a SINGLE VALUE RESULT.
Something similar to that, should bring what u need.
Select
companies.company_name, companies.last_login, companies.last_ip,
COUNT(*) AS audit_count
From
companies
Left Join
auditing_master On auditing_master.company_id = companies.id
Group by
companies.id
Did you try this? (No need a subquery because no where clause into it, and LEFT JOIN already add auditing_master rows grouped by company_id = companies.id)
Select
companies.company_name, companies.last_login, companies.last_ip,
COUNT(company_id) AS audit_count
From
companies
Left Join
auditing_master On auditing_master.company_id = companies.id
Group by
companies.id
EDIT
Maybe if you add IF statement to avoid COUNT when there is no auditing_master for a given company.
SELECT
companies.company_name, companies.last_login, companies.last_ip,
IFNULL(am.company_id,0,COUNT(am.company_id)) AS audit_count
FROM
companies
INNER JOIN
auditing_master am ON auditing_master.company_id = companies.id
GROUP BY
companies.id
Feel free to put the entire SQL... Because the problem can be somewhere else!