Select data based on another table - mysql

I have three tables, I'll just list the important columns
db_players
id | name
players
id | teamid | careerid
db_teams
The db_teams id links to the players teamid.
I need to run a query where I select rows from db_players as long as db_teams.id isn't in a row in players as teamid where the careerid = 1.
I've never attempted this type of query with mysql before, I know I could do two queries and involve php but I'm intrigued as to whether it's possible with a pure db query.
Thanks.
EDIT - simpler now.
SELECT dp.first_name
FROM tbl_foot_career_db_players dp
INNER JOIN tbl_foot_career_players p
ON p.playerid != dp.id
WHERE p.careerid = 1
The idea is that I want to return all rows from tbl_foot_career_db_players WHERE the id from that table isn't present in a row in tbl_foot_career_players in the column playerid. And the tbl_foot_career_players.careerid must also equal 1.

List all db_players that are not in players with career = 1
SELECT d.*
FROM db_players d
LEFT JOIN players p
ON p.player_id = d.id
AND p.career = 1
WHERE p.id IS NULL

Try to JOIN them with db_players id is not in players teamid.
SELECT db_players.* FROM db_players
LEFT JOIN players ON players.id != db_players.id
LEFT JOIN db_teams ON players.teamid = db_teams.id
WHERE careerid = 1

Related

How to Join three tables properly

The main table has 4 columns:
User Activity Table
userActivityId userId therapistId activityId
1 1 1 1
Each of these columns is a table and these values are all foreign keys.
Basically im trying to run a query that will join to the users table and pull their first and last name based off the user Id.Same thing with therapist - join to the therapist table, pull first + last name.And finally Join to the Activity table and pull the activity name and path from the activity Id
The other tables look like this:
User Table
userId fName lName
Therapist Table
therapistId therapistFirstName therapistLastName
Activity Table
activityId activityTitle activityPath
So far my query looks like
SELECT
User_Activities.userId,
User_Activities.therapistId,
User_Activities.activityId,
Activities.activityTitle,
Activities.activityPath,
Users.fName,
users.lName,
Therapists.therapistFirstName,
Therapists.therapistLastName
FROM
User_Activities
INNER JOIN Users
ON User_Activities.userId = Users.userId
INNER JOIN Therapists ON
User_Activities.therapistId = Therapists.therapistId
INNER JOIN Activities ON
Activities.activityId = User_Activities.userActivityId
WHERE
User_Activities.userId = 1;
When I run this query It only returns 1 row as a result. However there are two activities in the User_Activites table assigned to userId 1.
If I change : INNER JOIN Activities ON
Activities.activityId = User_Activities.userActivityId
from an INNER JOIN to the LEFT JOIN it will display the second row, however the activityTitle and activityPath will be displayed as NULL in the second row.
userActivityId userId therapistId activityId activityId activityTitle activityPath fName lName therapistFirstName therapistLastName
1 1 1 1 1 Brain GZZ0zpUQ S C M D
11 1 1 1 NULL NULL NULL S C M D
You have pretty much answered your question. The second activity does not have a valid ActivityId.
If you want all activities for a user, then you should phrase the query as:
SELECT . . .
FROM Users u LEFT JOIN
User_Activities ua
ON ua.userId = u.userId LEFT JOIN
Therapists t
ON ua.therapistId = t.therapistId LEFT JOIN
Activities a
ON a.activityId = ua.userActivityId
WHERE u.userId = 1;
You want to start with the table where you want to keep all the rows. Then use LEFT JOIN to bring in other tables.
Two other changes of note:
Table aliases are used to simplify reading and writing the query. The SELECT needs to change to use the aliases.
The WHERE clause refers to the Users table rather than UserActivities.

MySQL Joins on n to n relational table keping NULL values

This is a vote system, where candidate can be voted from different(limited) places. and I want the number of vote per place of each candidate.
I have 3 tables
TABLE candidate
------------------
id
name
TABLE place
------------------
id
label
TABLE vote
------------------
id
id_candidate
id_vote
no_votes // represents the amount of votes in this place for that particular candidate
Suppose I have 10 candidates and 15 different places, I'm trying to make a query that will return 10*15 = 150 rows even if there is no votes, keeping NULL value for ids that are not present in the relational table(which i can replace by 0).
But i'm not making the correct query
Here is the query i made so far (i've tried many modification, inner, outer joins... but nothing worked)
SELECT *
FROM votes
RIGHT JOIN candidate ON candidate.id = candidate_id
LEFT JOIN palce ON place.id = place_id
First, if you want the number of votes per candidate, then you should be thinking "aggregation".
Second, don't mix left and right joins in a query. It is just confusing. Start with the table where you want to keep all the rows, and then just use left join.
So, something like this:
SELECT c.*,
SUM(p.place_name = 'place1') as place1,
SUM(p.place_name = 'place2') as place2,
SUM(p.place_name = 'place3') as place3
FROM candidate c LEFT JOIN
votes v
ON c.id = v.candidate_id LEFT JOIN
place p
ON p.id = v.place_id
GROUP BY c.id;
Considering:
TABLE vote
------------------
id PK
id_candidate FK to candidate
id_vote FK to place
no_votes
-
SELECT CA.name,
PL.label,
SUM(VO.no_votes) as votes
FROM candidate CA
LEFT JOIN vote VO ON CA.id = VO.id_candidate
LEFT JOIN place PL ON PL.id = VO.id_vote
GROUP BY CA.id, PL.id

SELECT latest data from 2 joined tables

I have looked pretty hard through other SQL query questions but have been unable to narrow down a response that seems to work in my case... so here goes.
I have two mySQL tables:
players:
pid
pname
player_stats:
pid
statdate
rank
score
I would like to show output of the players name and their latest score and rank like this:
player1 | rank10 | 123345
player2 | rank15 | 480993
I have played around with max(statdate) and GROUP BY on pname but the closest I have gotten is below, which gives me the right number of rows but not the latest date (thus not the latest rank or score).
SELECT p.pname, s.rank, s.score
FROM players p INNER JOIN player_stats s ON p.pid = s.pid
GROUP BY p.pname
as mentioned this is close but the rank/score are not always the last date's
You can have an extra join in a subquery which separately get the latest date for every pid.
The subquery contains only two columns: pid and statdate. To get the other columns you need to join it with the other table.
SELECT a.pname, b.rank, b.score
FROM players a
INNER JOIN player_stats b
ON a.pid = b.pid
INNER JOIN
(
SELECT pid, MAX(statdate) statdate
FROM player_stats
GROUP BY pid
) c ON b.pid = c.pid
AND b.statdate = c.statdate

Select Rows From Second Table Based On id From First

I have 2 tables
1_products
id, code, make, model, fk_group_id
1_stock
id, stock, repair
I want to be able to return all of the rows in both tables based on the match in the first. Say WHERE fk_group_id = 11
Here is one:
SELECT *
FROM products AS p
INNER JOIN stock AS s ON p.id = s.id
WHERE fk_group_id = 11

Mysql Multiple ANDS

I have three tables persons, jobs, jobs_persons
One person can have multiple jobs.
Person 1 is Technical Support AND Manager
Person 2 is Technical Support
Person 3 Is Manager
Job 1 Technical Support
Job 2 Manager
I need to find a query give me the result for the person who currently is Technical Support AND Manager
The answer would be only Person 1
SELECT persons.*
FROM persons INNER JOIN jobs_persons ON persons.id = jobs_persons.person_id
INNER JOIN jobs ON jobs.id = jobs_persons.job_id
WHERE job.id IN (1,2)
Returns 3 rows
SELECT persons.*
FROM persons INNER JOIN jobs_persons ON persons.id = jobs_persons.person_id
INNER JOIN jobs ON jobs.id = jobs_persons.job_id
WHERE job.id = 1 AND job.id = 2
Returns 0 rows.
I'm currently working on Ruby on Rails.
Somebody can help?
You want to use an OR operator. Using job.id = 1 AND job.id = 2 will only return elements where id equals 1 and at the same time 2. No element can do that. You want elemets where th id is 1 or where the id is 2.
to make it more obvious:
SELECT * FROM table WHERE lastname = 'Smith' AND firstname = 'James';
when executing this you obviously don't want everybody who is called Smith or James. ;-)
EDIT:
Misread the question. what you need is a second join to join the jobs table two times in and join them with the different jobs. It is a bit hard as you didn't show the schema, but this might work:
SELECT persons.*
FROM persons
INNER JOIN jobs_persons jp1 ON persons.id = jp1.person_id
INNER JOIN jobs_persons jp2 ON persons.id = jp2.person_id
INNER JOIN jobs j1 ON j1.id = jp1.job_id
INNER JOIN jobs j2 ON j2.id = jp2.job_id
WHERE j1.id = 1 AND j2.id = 2
Try this to get all the person who has got a job of 1 AND 2 in your associative entity table. No need to hit the job table.
SELECT p.*
FROM persons p
WHERE id in (
SELECT person_id FROM jobs_persons
WHERE job_id IN (1,2)
GROUP BY person_id
HAVING COUNT(*) = 2
);
With your recent comments, it seems you're having performance problems. That's really outside of the scope of this question and answer.
You need to make sure your indexes are in place on the appropriate columns:
jobs_person.job_id
persons.id