Can somebody explain what is wrong with this INNER JOIN? - mysql

Simplified, I have three tables in a MySQL database:
sessions
- id
- title
- training_programme_id
session_attendees
- id
- sessions_id
- users_id
users
- id
- name
I am trying to count the number of sessions that a user is attending on a given training programme. When a user is set to attend a session, their ID is added to session_attendees.users_id and the session ID is added to session_attendees.sessions_id. Here is my SQL to count (as result) the number of sessions attended by a user with ID 10 when the training programme ID is 1:
SELECT count(*) AS result FROM session_attendees
INNER JOIN sessions
ON (session_attendees.sessions_id = sessions.id)
WHERE (session_attendees.users_id = 10 AND sessions.training_programme_id = 1);
Now I know from directly inspecting the database that session_attendees contains 7 sessions where users_id = 10 and all of those sessions have a training_programme_id = 1.
Am I misunderstanding an INNER JOIN?
EDIT:
Here's a couple of images to illustrate my tables:
As you can see I've sorted by user ID so you can see the 7 entries for ID = 10.

Related

Getting X results from SQL with multiple tables

(Sorry for my bad english, I'll try to be the clearest)
I want to select 5 conversations (over an undetermined number, there could be 5 or 300 conversations) of one user in a MySQL table, and for each of those, I want to select all the users who talk in it.
In a wonderfull world, I'd like to do it with one query.
My query looks like (tables are in french, plz don't hurt me) :
SELECT mc.mc_id, mc.mc_sujet, mc.mc_statut,
miu.mi_ustatut as uself_statut, miu.mi_datelecture as uself_datelecture,
mi.mi_uid, mi.mi_ustatut, mi.mi_datelecture,
u.u_pseudonyme
FROM msg_individus as miu
LEFT JOIN msg_conversations as mc ON mc.mc_id = miu.mi_mcid
LEFT JOIN msg_individus as mi ON mi.mi_mcid = mc.mc_id
LEFT JOIN u_individus as u ON u.u_id = mi.mi_uid
WHERE miu.mi_uid = :u_id
Where msg_individus is the table with participants of a conversation,
msg_conversations is the table of the conversation (id, subject, status),
u_individus is the table with users' informations.
To select only 5 of those conversations, I added something like
GROUP BY mc.mc_id,
LIMIT 0,5
But of course, only one user per conversation is given is this way.
I also tried to write GROUP BY mc.mc_id, mi.mi_uid but this, like no writting a GROUP BY condition, returns 5 iterations like :
(Conversation 1 has two users, conversation 2 has one, conversation 3 has four)
Iteration 1 : conversation 1, user 1
Iteration 2 : conversation 1, user 2
Iteration 3 : conversation 2, user 1
Iteration 4 : conversation 3, user 1
Iteration 5 : conversation 3, user 2
What I want is to get five CONVERSATIONS with all their datas (whatever the number of users in it, etc)
I guess I'll have to use two queries (after getting the 5 conversations, I'll get the users per conversations), but maybe you guys can light me with your knowledges.
Thx.
Use a subquery to get five conversations. I also suggest that you replace the outer joins with inner joins. I think the table keys should all have matches:
SELECT mc.mc_id, mc.mc_sujet, mc.mc_statut,
miu.mi_ustatut as uself_statut, miu.mi_datelecture as uself_datelecture,
mi.mi_uid, mi.mi_ustatut, mi.mi_datelecture,
u.u_pseudonyme
FROM (SELECT miu.*, mc.*
FROM msg_individus miu JOIN
msg_conversations mc
ON mc.mc_id = miu.mi_mcid
WHERE miu.mi_uid = :u_id
ORDER BY rand() -- not necessary, but why not?
LIMIT 5
) ic
msg_individus mi
ON mi.mi_mcid = ic.mc_id JOIN
u_individus u
ON u.u_id = ic.mi_uid;

Showing null rows on a quiz application when user has no quiz results

Summary of problem: I have a CakePHP/MySQL web application. Users do quizzes to be awarded badges. Each quiz has a level (1 up to 5) to represent difficulty (1 = Easy, 5 = difficult).
I have 3 tables:
quizzes : A series of quizzes, each of which have a difficulty level 1 - 5 (quizzes.test_level) field and a unique ID (quizzes.id).
badge_structure : A list of quizzes which are required to gain a particular badge. Foreign key to 'quizzes' is badge_structure.quiz_id. This table contains multiple quizzes at each test_level.
results : A list of users results for a particular quiz. Foreign key is results.quiz_id. There is also a results.user_id to link to a 'users' table. Results are only stored in this table if the user has passed a quiz: If there is no results.quiz_id in this table for a given user, that user has not passed a particular quiz.
The problem I'm facing is I cannot work out which level the user has passed.
My application needs to show a star rating (1 - 5) based on quiz results for a given user. They must have completed all quizzes at a particular level (quizzes.test_level) to be awarded the star for a given badge, i.e.
quizzes.test_level = 1 (1 star)
quizzes.test_level = 2 (2 stars)
For the code below assume badge_structure.id = 3 (Badge number 3) and user.id = 257
SELECT MAX(q.test_level) AS badge_level
FROM badges_structure bs
JOIN quizzes q ON bs.quiz_id = q.id
JOIN results r ON bs.quiz_id = r.quiz_id
WHERE bs.badge_id = 3 AND r.user_id = 257
ORDER BY q.test_level ASC
This will give me the maximum test_level of a quiz a user has done, for a given badge. But I don't know whether they have passed that level, I only know that they have done quizzes that are within that level.
If I run something like this:
SELECT bs.badge_id, bs.quiz_id, q.test_level
FROM badges_structure bs
LEFT JOIN quizzes q ON bs.quiz_id = q.id
LEFT JOIN results r ON bs.quiz_id = r.quiz_id
WHERE bs.badge_id = 3 AND r.user_id = 257
ORDER BY q.test_level ASC
I can see the quizzes and levels they have done, but it doesn't tell me the whole badge_structure for that badge, because it's not including rows where they haven't yet got results.
How is it possible to see the badge structure and have a column which is 'null' if the user has no quiz results for a particular quiz ID?

Database Schema and Sql for a 5 star Rating

Requirements:
1. All "Users" have 5 fixed set of same "Services" which they are supposed to rate.
2. Given the userId, display all the Services and their corresponding "Ratings".
3. Rating would be from a scale of 1 - 5 only
4. Ratings can be updated anytime by the user for any of his Service.
I am no SQL/DB expert and I had this question up in stacks for which I got answer from Raj here ER Model of User Ratings
This is the ER I finalized (open for correction).
My Fetch Query: Get all the services and their corresponding for a userId (say userId = 1)
SELECT service.service_id, service.name, usr.ratings
FROM services service,
ratings ratings,
userservices_ratings usr,
user user,
user_services us
where
us.userid = user.uid and
us.serviceid = service.serviceid and
usr.usid = us.id and
usr.rid = ratings.rid and
user.id = 1
The above query will return all the services and ratings, only if User has rated the service. For services which are unrated don't make it to result set. So I assume I should pre-populate unrated services with a default value say 0?
All users will have fixed set of 5 services all the time, do I write a trigger to create his entry into User_Services table whenever a User is created?
How would the create/update query look if for example a Userid = 1, rates = 3 for serviceId = 1?
Any flaw in the schema?
You can standard format of Rating Schema here https://schema.org/Rating
You can pick required columns from this

Mysql join queries not returning all rows as it should

I have an event software. The first table stores individuals who signed up for an event: EventIndividuals. I have a second table that stores the t-shirt they selected as a gift when they attend the event: EventIndividualShirtXref.
When I run the following query to see how many individuals are attending the 1st event it returns 31 rows correctly:
SELECT Id
FROM EventIndividuals
WHERE EventId = 1
Then when I run my second query to pair them up with a shirt it only returns 22 rows:
SELECT *
FROM EventIndividualShirtXref
WHERE EventIndividualId IN(SELECT Id FROM EventIndividuals WHERE EventId = 1)
I also tried running the next query using a join and it still only returns 22 rows:
SELECT esx.*
FROM EventIndividualShirtXref esx
INNER JOIN EventIndividuals ei
ON esx.EventIndividualId = ei.Id
WHERE ei.EventId = 1
I checked the indexing and the the columns are indexed correctly.
Is this enough info provided to figure out why the 31 rows are cut to 22?
This has never happened to me before and it makes no sense.

MYSQL - How to check if a user is following another user, potentially through a subselect?

I'm fetching a list of activities (activities) and using a left join to grab the user data (users) who created the activity. Within my application users have the ability to follow one another.
This is my current query, which grabs all activities not posted by yourself ($user_id)
SELECT
activities.id, activities.user_id, users.id, users.name
FROM
activities
LEFT JOIN
users on activities.user_id = users.id
WHERE
users.id != $user_id
Aside from the activities + users tables, I have a another table in my application called followers:
followers
id | user_id_1 | user_id_2 | followed_back
1 1 3 1
2 2 3 0
3 3 1 1
I need to check whether you ($user_id) have followed a particular user joined to each activity and perhaps call this new field "user_followed" which represents a true/false/null value?
For example, I'm user_id = 1. Based on the above table, this means I have followed user_id 3. When an activity is fetched and user_id 3 is joined / responsible, the new field "user_followed" would be true.
Therefore, I think I'd need to incorporate another SELECT query, checking if the user is being followed:
(SELECT
*
FROM
followers
WHERE
user_id_1 = $user_id AND user_id_2 = users.id
)
I'm just largely unsure of how to incorporate this into my initial query and create a new field representing yes or no. Any help would be much appreciated!