MYSQL Count where active across tables - mysql

I have three tables:
person
-----------
person_id, active
person_team
-----------
person_id, team_id, active
team
-----------
team_id, active
I'd like to get the count on teams from each person where active is true in each table.
So far I have:
SELECT t.id, t.title, t.created_timestamp, COUNT(p_t.tag_id) AS count
FROM team t
LEFT JOIN
person_team p_t ON p_t.team_id = t.id AND p_t.active = 1
WHERE
t.active = 1
GROUP BY t.id
ORDER BY t.title
This gets the count where team and person - team are active, but doesn't take into account whether person is active. Should I use a sub query or another type of join?

You need to add the person table in a join, and count a column from that table:
SELECT t.id, t.title, t.created_timestamp, COUNT(p.id) AS count
FROM team t
LEFT JOIN
person_team p_t ON p_t.team_id = t.id AND p_t.active = 1
LEFT JOIN
person p ON p_t.person_id = p.id AND p.active = 1
WHERE
t.active = 1
GROUP BY t.id
ORDER BY t.title

You should use a inner join on sub select for get the columns not in group by
select k.id, t.title, t.created_timestamp, k.count from
( SELECT t.id COUNT(p_t.tag_id) AS count
FROM team t
LEFT JOIN
person_team p_t ON p_t.team_id = t.id AND p_t.active = 1
WHERE
t.active = 1
GROUP BY t.id ) k
inner join team t on t.id = k.id

Related

How to solve difference in number of records from a union query

I have a list of technicians and their number of patients, when I click on a technician I get the list of patients and their details.
To do this, I have query that Returns the number of patients per technician and another returns the records of the patients.
SELECT *, SUM(Rcount) as Number_of_patients
FROM
(
SELECT users.users_id, users.name, patients.patients_id, count(*) as Rcount
FROM pecs
INNER JOIN users ON pecs.techniciens_id = users.users_id
INNER JOIN titles ON users.titles_id = titles.titles_id
INNER JOIN patients ON patients.patients_id = pecs.patients_id
GROUP BY users_id
UNION ALL
SELECT users.users_id, users.name, patients.patients_id, count(*) as Rcount
FROM followup
INNER JOIN users ON followup.technician_id = users.users_id
INNER JOIN titles ON users.titles_id = titles.titles_id
INNER JOIN pecs ON pecs.pecs_id = followup.pecs_id
INNER JOIN patients ON patients.patients_id = pecs.patients_id
GROUP BY users_id
)x
GROUP BY users_id ORDER BY last_name ASC
the result is:
users_id | name | Number_of_patients
40 | ABABAB | 223
that is 223 patients for technician_ID = 40
Now to view a list of the patients for this technician I have the following query:
SELECT *
FROM
(
SELECT patients.patients_id, patients.name
FROM pecs
LEFT JOIN users ON pecs.techniciens_id = users.users_id
LEFT JOIN titles ON users.titles_id = titles.titles_id
INNER JOIN patients ON patients.patients_id = pecs.patients_id
WHERE pecs.techniciens_id = 40
#GROUP BY patients_id
UNION ALL
SELECT patients.patients_id, patients.name
FROM followup
LEFT JOIN users ON followup.technician_id = users.users_id
LEFT JOIN titles ON users.titles_id = titles.titles_id
LEFT JOIN pecs ON pecs.pecs_id = followup.pecs_id
INNER JOIN patients ON patients.patients_id = pecs.patients_id
WHERE followup.technician_id = 40
#GROUP BY patients_id
)x
GROUP BY patients_id ORDER BY last_name ASC
Now, I get the same number of records (223) but there are duplicates rows of patients ...I need help on how to get the correct number of patients for each technician without duplicates.
Can anyone please help?
I am not sure I understood exactly your question. Anyway, I would try to keep things as simple as possibile. Regarding your "count" query, you could start from something like this, where I removed filed I think should not be useful for counting. This query should give you count avoiding multiple id (I use DISTINCT in the two select and UNION to remove possible duplicate between the two select). May be some join could be eliminated (but I don't know the whole structure). Please follow Tim B. suggestion about formatting and care in posting a question.
SELECT USERS_ID, COUNT(*) AS PATIENTS_COUNT
FROM (
SELECT DISTINCT USERS.USERS_ID, PATIENTS.PATIENTS_ID
FROM PECS
INNER JOIN USERS ON PECS.TECHNICIENS_ID = USERS.USERS_ID
INNER JOIN TITLES ON USERS.TITLES_ID = TITLES.TITLES_ID
INNER JOIN PATIENTS ON PATIENTS.PATIENTS_ID = PECS.PATIENTS_ID
UNION
SELECT DISTINCT USERS.USERS_ID, PATIENTS.PATIENTS_ID
FROM FOLLOWUP
INNER JOIN USERS ON FOLLOWUP.TECHNICIAN_ID = USERS.USERS_ID
INNER JOIN TITLES ON USERS.TITLES_ID = TITLES.TITLES_ID
INNER JOIN PECS ON PECS.PECS_ID = FOLLOWUP.PECS_ID
INNER JOIN PATIENTS ON PATIENTS.PATIENTS_ID = PECS.PATIENTS_ID
) A

Count two different rows in mysql query

I have organizations. Each organization can have members and projects.
I want to get list of organizations with number of members and projects.
For example,
Organization | Members | Projects | Action
------------------------------------------
Org 1 | 5 | 6 | Delete - Edit
Org 2 | 2 | 9 | Delete - Edit
I am using this query,
SELECT COUNT(m.id) as members, COUNT(p.id) as projects,
o.status,o.organization_name,o.logo, o.id as id
from tbl_organizations o
LEFT JOIN tbl_organization_members m ON (o.id = m.organization_id)
LEFT JOIN tbl_projects p ON (o.id = p.organization_id)
WHERE o.status= 'active' AND o.created_by= 1
But the output of number of projects is equal to number of members.
How can I make the sample above using query?
Try this way:
SELECT o.id as id, o.organization_name, cnt_ as members, cnt_p as projects
from tbl_organizations o
LEFT JOIN (
SELECT organization_id, COUNT(id) cnt_m
FROM tbl_organization_members
GROUP BY organization_id
) m ON (o.id = m.organization_id)
LEFT JOIN (
SELECT organization_id, COUNT(id) cnt_p
FROM tbl_projects
GROUP BY organization_id
) p ON (o.id = p.organization_id)
WHERE o.status= 'active' AND o.created_by= 1
This way you JOIN to an already aggregated version of member/project tables, so as to get the count of members/projects per organization_id.
Group by the organisation columns and count distinct IDs
SELECT o.status,o.organization_name, o.logo, o.id as id,
COUNT(distinct m.id) as members, COUNT(distinct p.id) as projects,
from tbl_organizations o
LEFT JOIN tbl_organization_members m ON (o.id = m.organization_id)
LEFT JOIN tbl_projects p ON (o.id = p.organization_id)
WHERE o.status= 'active'
AND o.created_by= 1
GROUP BY o.status, o.organization_name, o.logo, o.id
You can co-related subquery:
SELECT
o.id as Organization,
(SELECT COUNT(*) FROM tbl_organization_members WHERE organization_id = o.id) as members,
(SELECT COUNT(*) FROM tbl_projects WHERE organization_id = o.id) as projects
FROM
tbl_organizations o
WHERE
o.status= 'active' AND o.created_by = 1

Merge 2 SQL Queries/Tables

I spent so much time googling today but i don't even know which keywords to use. So …
The project is an evaluation of a betting game (Football). I have 2 SQL Queries:
SELECT players.username, players.userid, matchdays.userid, matchdays.points, SUM(points) AS gesamt
FROM players INNER JOIN matchdays ON players.userid = matchdays.userid AND matchdays.season_id=5
GROUP BY players.username
ORDER BY gesamt DESC
And my second query:
SELECT max(matchday) as lastmd, points, players.username from players INNER JOIN matchdays ON players.userid = matchdays.userid WHERE matchdays.season_id=5 AND matchday=
(select max(matchday) from matchdays)group by players.username ORDER BY points DESC
The first one adds up the points of every matchday and shows the sum.
The second shows the points of the last gameday.
My Goal is to merge those 2 queries/tables so that the output is a table like
Rank | Username | Points last gameday | Overall points |
I don't even know where to start or what to look for. Any help would be appreciated ;)
use both query with join....use inner join if each userid have value in 2nd query also.also add userid in 2nd query also for join
SET #rank = 0;
SELECT #rank := rank + 1,
t1.username,
t2.points,
t1.gesamt
FROM (
SELECT players.username, players.userid puserid, matchdays.userid muserid, matchdays.points, SUM(points) AS gesamt
FROM players INNER JOIN matchdays ON players.userid = matchdays.userid AND matchdays.season_id=5
GROUP BY players.username
)t1
INNER JOIN
(
SELECT players.userid, max(matchday) as lastmd, points, players.username
from players INNER JOIN matchdays ON players.userid = matchdays.userid
WHERE matchdays.season_id=5 AND matchday=
(select max(matchday) from matchdays)group by players.username
)t2
ON t1.puserid = t2.userid
ORDER BY t1.gesamt
You can use conditional aggregation, i.e. sum the points only when the day is the last day:
SELECT
p.username,
SUM(case when m.matchday = (select max(matchday) from matchdays) then m.points end)
AS last_day_points,
SUM(m.points) AS total_points
FROM players p
INNER JOIN matchdays m ON p.userid = m.userid AND m.season_id = 5
GROUP BY p.userid
ORDER BY total_points DESC;
Or with a join instead of a non-correlated subquery (MySQL should come to the same execution plan):
SELECT
p.username,
SUM(case when m.matchday = last_day.matchday then m.points end) AS last_day_points,
SUM(m.points) AS total_points
FROM players p
INNER JOIN matchdays m ON p.userid = m.userid AND m.season_id = 5
CROSS JOIN
(
select max(matchday) as matchday
from matchdays
) last_day
GROUP BY p.userid
ORDER BY total_points DESC;

sql select distinc where max date

I have 3 tables "maintenances", "cars", "users" . I want to select all data from table maintenance with a distinct car_id and the last record for each distinct (based on max maintenance_date)
SELECT
m. * , u.username, c.Model, c.Make, c.License, c.Milage, COUNT( m.process_id ) AS count_nr
FROM
maintenances AS m
LEFT JOIN users AS u ON u.id = m.user_id
LEFT JOIN cars AS c ON c.id = m.car_id
WHERE
maintenance_date = (SELECT MAX(maintenance_date) FROM maintenances WHERE car_id = m.car_id)
The problem is that this query returns only one record which has the max date from all records. I want all records (distinct car_id and from records with the same car_id to display only values for max(maintenance_date))
This is your query:
SELECT m. * , u.username, c.Model, c.Make, c.License, c.Milage, COUNT( m.process_id ) AS count_nr
----------------------------------------------------------------^
FROM maintenances AS m LEFT JOIN
users AS u
ON u.id = m.user_id LEFT JOIN
cars AS c
ON c.id = m.car_id
WHERE maintenance_date = (SELECT MAX(maintenance_date) FROM maintenances WHERE car_id = m.car_id);
It is an aggregation query. Without a group by, only one row is returned (all the rows are in one group). So, add the group by:
SELECT m. * , u.username, c.Model, c.Make, c.License, c.Milage, COUNT( m.process_id ) AS count_nr
FROM maintenances AS m LEFT JOIN
users AS u
ON u.id = m.user_id LEFT JOIN
cars AS c
ON c.id = m.car_id
WHERE maintenance_date = (SELECT MAX(m2.maintenance_date) FROM maintenances m2 WHERE m2.car_id = m.car_id);
GROUP BY c.id
I also fixed the correlation statement, to be clear that it is correlated to the outer query.
add GROUP BY u.username .
WHERE
maintenance_date = (SELECT MAX(maintenance_date) FROM maintenances WHERE car_id = m.car_id)
GROUP BY u.username

Collecting data from 3 tables into 1 query

I have three different tables in my MySQL database.
table users: (id, score, name)
table teams: (id, title)
table team_Members: (team_id, user_id)
What I would like to do is to have 1 query that finds every team ID a given user ID is member of, along with the following information:
total number of members in that team
the name of the team
users rank within the team (based on score)
EDIT:
Desired output should look like this;
TITLE (of the group) NUM_MEMBERS RANK
------------------------------------------------
Foo bar team 5 2
Another great group 34 17
.
.
.
The query should be based on the users ID.
Help is greatly appreciated
I think this query should get what you ask for
select t.id, t.title, count(m.user_id) members, (
select count(1)
from users u3
inner join team_Members m3 on u3.id = m3.user_id
and m3.team_id = t.id and u3.score > (
select score from users where name = 'Johan'
)
) + 1 score
from teams t
inner join team_Members m on t.id = m.team_id
where t.id in (
select team_id
from team_Members m2
inner join users u2 on m2.user_id = u2.id
where u2.name = 'Johan'
)
group by t.id, t.title
To collect you just need use JOIN
SELECT
u.*, t.*, tm.*
FROM
users u
JOIN
team_Members tm ON u.id = tm.user_id
JOIN
teams t ON t.id = tm.team_id;
To get total of number of that team use COUNT with some group key
Some like that
SELECT
COUNT(t.id), u.*, t.*, tm.*
FROM
users u
JOIN
team_Members tm ON u.id = tm.user_id
JOIN
teams t ON t.id = tm.team_id GROUP BY t.id;
And to rank just:
SELECT
COUNT(t.id) as number_of_members, u.*, t.*, tm.*
FROM
users u
JOIN
team_Members tm ON u.id = tm.user_id
JOIN
teams t ON t.id = tm.team_id
GROUP BY t.id
ORDER BY u.score;