I got stucked with this query in the past couple of hours, and I badly need someone to help me figure it out. I'm try to finish my private message system, but I lost myself in the database tables. I've created three tables for the system, and they are as follows:
CONVERSATION(**conversation_id**, subject)
CONVERSATION_MEMBER(**conversation_id**, **user_id**, conversation_last_view, conversation_deleted)
CONVERSATION_MESSAGE(**message_id**, conversation_id, user_id, message_date, message_text)
Ok, so in my function to get all conversations of a specific user, I'm fetching the subject, the date, and at last I want to show the user who is he/she talking to. I wrote the following query:
SELECT
c.conversation_id,
c.conversation_subject,
MAX(cmes.message_date) AS conversation_last_reply,
FROM conversation c, conversation_member cmem, conversation_message cmes
WHERE c.conversation_id = cmes.conversation_id
AND c.conversation_id = cmem.conversation_id
AND cmem.user_id = {$_SESSION['user_id']}
AND cmem.conversation_deleted = 0
GROUP BY c.conversation_id
ORDER BY conversation_last_reply DESC
And, at last I'm tryin to get the user's first and last name (the other user in the conversation), but I lost myself on how to do that. I've tried to create another function that will get the conversation id, while looping through the results of the first query, and return the user's first and last name, but it didn't work out.
Btw, for the users I have another table... I guess I don't have to tell you. Ok, thank you.
$sql = "SELECT (user.forename, user.surname, other_fields...)
FROM conversation
INNER JOIN conversation_member
ON conversation.conversation_id = conversation_member.conversation_id
INNER JOIN conversation_message
ON conversation.conversation_id = conversation_message.conversation_id
INNER JOIN users_table /* replace this with the name of your user table */ AS user
ON user.user_id = conversation_member.user_id
WHERE user.user_id = :userid
AND conversation_member.conversation_deleted = 0
GROUP BY conversation.conversation_id;"
$query = $db->prepare($sql);
$query->bindParam(':userid', $userid, PDO::PARAM_INT);
$query->execute();
$results = $query->fetchAll();
$user = $results[0]["user"]; //stores array of user fields (forename, surname, etc)
SELECT
c.conversation_id,
c.conversation_subject,
user.firstname,
user.lastname,
MAX(cmes.message_date) AS conversation_last_reply,
FROM conversation c, conversation_member cmem, conversation_message cmes, user_tablename user
WHERE c.conversation_id = cmes.conversation_id
AND c.conversation_id = cmem.conversation_id
AND cmem.user_id = {$_SESSION['user_id']}
AND cmem.conversation_deleted = 0
AND user.user_id_column = whatever.you_used_as_foriegn_key
GROUP BY c.conversation_id
ORDER BY conversation_last_reply DESC
Assuming the columns names are like that
You need to join with the "conversation_member" table again, this time, selecting the other user's id where the same conversation_id and message_id applies:
SELECT
c.conversation_id,
c.conversation_subject,
MAX(cmes.message_date) AS conversation_last_reply,
cmem2.user_id AS other_user_id
CONCAT(usr_tbl.firstname, ' ', usr_tbl.lastname) AS other_user_name
FROM conversation c
JOIN conversation_member cmem
JOIN conversation_message cmes
JOIN conversation_member cmem2
JOIN users_table usr_tbl
ON c.conversation_id = cmes.conversation_id
AND c.conversation_id = cmem.conversation_id
AND cmem.user_id = {$_SESSION['user_id']}
AND cmem.conversation_deleted = 0
AND c.conversation_id = cmem2.conversation_id
AND cmem2.user_id = {$_SESSION['other_user_id']}
AND cmem2.conversation_deleted = 0
GROUP BY c.conversation_id
ORDER BY conversation_last_reply DESC
I don't see why you're having trouble getting the user's first and last name if you were able to construct the rest of that query by yourself?
Try something along the lines of, :
SELECT cmem.user_id, u.first_name, u.last_name, c.conversation_id, c.conversation_subject, MAX(cmes.message_date) AS conversation_last_reply
FROM conversation c
INNER JOIN conversation_member cmem on c.conversation_id=cmem.conversation_id
INNER JOIN conversation_message cmes on c.conversation_id=cmes.conversation_id
INNER JOIN users u on u.user_id = cmem.user_id
WHERE cmem.user_id = {$_SESSION['user_id']} AND cmem.conversation_deleted = 0
GROUP BY cmem.user_id, u.first_name, u.last_name, c.conversation_id, c.conversation_subject
Now, I think you should also be reconsidering your database structure so that all these joins are not necessary. I see several problems. One, your database seems to be over-normalized. Why do you have a separate "Conversations" table that has only two fields, conversation id and subject? In any message system I've ever seen, the subject is always visible so you would always have to join the conversation table just to get the subject field. The conversation_id is in every other table anyway. Just add the subject field to the message table and eliminate the conversation table if that's all it's holding, normalization isn't always a good thing.
Second, why do you set a flag for deleted messages instead of just deleting them? I've also never seen a message system that lets me restore messages I've deleted. At the very least, if you want to retain them for whatever reason you should move them to an archive table so that the primary table you're running selects off of doesn't have to deal with the performance hit of parsing through meaningless "deleted" entries.
Lastly, what is the conversation_member table anyway? Based on my interpretation, it's supposed to represent a member of the conversation since it has a user_id. Why would the conversation delete flag be present for a single member of a conversation? If anything it should be in the conversation table. With that improvement, the only field left in it is conversation_last_view, which really no one cares about. The more important thing is conversation_last_post, which can be easily derived from the timestamp of the last message posted in the thread.
Ultimately, if you just want to see the first and last names appended to your query it's as simple as joining the users table and displaying those two entries. The SQL query I provided should get you close if it doesn't work straight out, I'm too lazy to copy your database and try it myself. However, I think you should really consider the overall design of your database as well so you don't run into needless performance issues down the road.
To answer the question of: Finding all users in a conversation, MINUS the current user:
SELECT (users.forename, users.surname)
FROM conversation_members AS members
INNER JOIN users_table AS users
ON members.user_id = users.user_id
WHERE members.conversation_id = :conversationid
AND NOT users.user_id = :userid
Where :userid is the current user and :conversationid is the conversation in question.
Related
I have to make a scores page for a game and one thing it has to display is the number of times the current user has played the game. Basically what i need to select ID and username from one table, link them together and count the corresponding user IDs from another table.
These are the tables I was given: Users --> ID, USERNAME and Times_Played --> ID, USER_ID
Thanks in advance
You want to query something like this:
SELECT Users.USERNAME, Times_Played.User_ID
FROM Users
INNER JOIN Times_Played
ON Users.ID=Times_Played.ID;
EDIT
After re-reading the question and seeing the need to count the times played you could do this via PHP or via your SQL Query. Via PHP:
$result = mysqli_query(
"SELECT Users.USERNAME, Times_Played.User_ID
FROM Users
INNER JOIN Times_Played
ON Users.ID=Times_Played.ID"
);
$timesPlayed = mysqli_num_rows($result);
If it has to be done via the query, Anish has the correct solution.
I hope that helps.
Try this
select count(*) as Times_Played,Users.USERNAME,Users.ID
from Users
inner join Times_Played
on Users.ID = Times_Played.USER_ID
I have 5 tables:
user ( user id, user name, etc.. )
role ( role_id, role_name )
user_role ( user_id, roles_id )
form ( form_id, form_name, etc.. )
form_access ( form_id, role_id )
user contains all registered user data.
role contains all different types of roles.
user_role contains which user has which role (all assigned roles are stored)
form contains all form data.
form_access contains data like which user role has which form access(one form can be assigned to many user roles).
I wanted to write a SQL query in PHP to retrieve form name based on the user logged in and his role, e.g. if Admin logs in he should get all forms, if HR logs in he should get forms related to HR only.
I tried this query:
$query = "SELECT ur.role_id, f.form_name, f.form_desc
FROM user_role ur, froms f
WHERE users.id = '".$user."',
users.status ='A',
forms.form_id = form_access.form_id,
from_access.role_id = user_role.role_id,
user_role.role_id = '".$user."'";`
Some one help me out with the correct query?
Since you start from the user_id you'll want to select from user_role and JOIN form_access and form.
SELECT `form`.`form_name` AS `form_name`
FROM `user_role` AS `ur`
INNER JOIN `form_access` AS `fa` ON `fa`.`role_id` = `ur`.`role_id`
INNER JOIN `form` AS `f` ON `f`.`form_id` = `fa`.`form_id`
WHERE `ur`.`user_id` = '".$user."'
PS: Check the table and column names.
You have to use AND .
BUT this should be better with joins.
$query = "SELECT ur.role_id, f.form_name, f.form_desc
FROM from_access
INNER JOIN froms f ON forms.form_id = form_access.form_id
INNER JOIN user_role ur ON from_access.role_id = user_role.role_id
INNER JOIN users ON users.id = user_role.role_id
WHERE users.id = '".$user."'
AND users.status ='A' ";
Your query is entirely broken, the others may have provided you with solutions but I'm going to give you some advice.
You've written an entire query, tried it, and it failed. I write queries all day long but if I write a whole query in Notepad then execute it it's probably going to have some minor error in it somewhere too.
Start from the ground up. You're trying to get a list of forms the user has access to, so lets start with the forms_access table. So what's the most basic starting point? How about:
SELECT fa.role_id, fa.form_id
FROM forms_access fa
Ok, thats overly simplified but if that ran at least we know we're connected to the database.
So we can easily tell which form_ids each role has access to. Now we know our linking table to users is user_roles, so let's add that in:
SELECT ur.user_id, fa.form_id, fa.role_id
FROM forms_access fa
INNER JOIN user_roles ur ON fa.role_id = ur.role_id
So we've joined forms_access to user_roles on the foreign key role_id. Now we can see for every user_id, which role_id they have and which form_ids they can access.
So we're pretty much there, we just need the information from the forms table, so lets JOIN to that too:
SELECT ur.user_id, f.form_name, f.form_desc, fa.form_id, fa.role_id
FROM forms_access fa
INNER JOIN user_roles ur ON ur.role_id = fa.role_id
INNER JOIN forms f ON f.form_id = ur.form_id
Great! Now we have a list of each form_name/form_desc that each user_id can access.
Try the above step by step, if you skip to the end there could well be an error since I have not tested the code, and I don't know for sure that your table definitions match the question. If you do it step by step you only need to check the most recently added line to find the error.
I have just noticed in the question that you also need users.status = 'A', so in the same way as above you'll need to join to the users table on an appropriate foreign key, give it a go.
Now, once you've done all that you need to filter the results to a specific user_id - notice up till this point we haven't bothered with the WHERE clause.
Now don't go adding some variant of WHERE user_id = '$user' right away because then you've introduced 2 potential errors. Instead try adding WHERE user_id = 0 (or some known user_id). Does the query run and the results look correct? Great, now finally try adding in your php variable.
I am somewhat new to coding and have been trying to write what I thought would be a straightforward sql query. Please help :)
Table 1: Users
id = user idt
username = user name
Table 2: Orders
orderid = order id
order_to = user id of person buying
order_from = user id of person selling
oder_details = text
Basically I want to:
"Select Username(from), Username(to), order_details FROM mytables WHERE Order id = 1;"
And get the result as 1 row, I'm not sure how to proceed. I thought I could do this with concatenation or something... Can anyone help?
You need to use JOIN to link the tables together.
SELECT fu.username AS fromUser, tu.username AS toUser, o.order_details
FROM Orders o
INNER JOIN Users fu
ON fu.id = o.order_to
INNER JOIN Users tu
ON tu.id = o.order_from
WHERE o.orderid = '1';
Because you have two different users that you need the username from, you need to JOIN the Users table twice to get both user's usernames. Each table needs to have it's own alias fu and tu to allow MySQL to differentiate between them. The same goes for the column names in your SELECT statement so that when you fetch the results with PHP, php can differentiate between the two usernames.
You are looking for a JOIN. This can be done with a keyword or through WHERE clauses. For example,
SELECT * FROM Orders JOIN Users ON Orders.order_to=Users.id
The documentation can be found here: http://dev.mysql.com/doc/refman/5.0/en/join.html.
I'll leave it as an exercise to figure out how to JOIN the order_from.
I need to filter data based on one table, but i dont know the correct usage for the select from function in php mysql. The below code shows what i am trying to do, but I think you can use multiple SELECT.
$query_Student = "SELECT Project_Title, Project_Lecturer FROM projects WHERE Project_id =
(SELECT Proj_id FROM project_course WHERE Cour_id = (SELECT Course_id from courses WHERE
Code = (SELECT Course FROM users WHERE Username = ".$_SESSION['MM_Username']."))"
Can anyone offer any assistance to what I need to write instead?
What you want to do is not exactly clear to me, but to make your query work you need to put single quotes around $_SESSION['MM_Username'], like gogowitsch already said.
Also another closing paranthese is missing. So your query should look like this:
$query_Student = "SELECT Project_Title, Project_Lecturer FROM projects WHERE Project_id =
(SELECT Proj_id FROM project_course WHERE Cour_id = (SELECT Course_id from courses WHERE
Code = (SELECT Course FROM users WHERE Username = '".$_SESSION['MM_Username']."')))"
But...
That is not a very well written query.
I'm just guessing now, but maybe this is what you are looking for:
SELECT
p.Project_Title,
p.Project_Lecturer
FROM projects p
INNER JOIN project_course pc ON p.Project_id = pc.Proj_id
INNER JOIN courses c ON pc.Cour_id = c.Course_id
INNER JOIN users u ON c.Code = u.Course
WHERE u.Username = 'yourUserName';
If not, show us the tables you are using (do a SHOW CREATE TABLE projects; and so on for every table you are using and post it here) and maybe what output you expect, then we can really help.
You might need to add quotes around the username. Can $_SESSION['MM_Username'] be a string?
basicalli, i have a table: friends [id, fromid, toid]
[fromid] and [toid] represents the id of the user, fromid is who asked, and toid who acepted.
I consider two users 'friends' where ther is to items in friends table for each.
example: user 1 is friend of user 2 when i have:
in table friends:[id,1,2],[id,2,1],....
Im trying with this query and as i said in title gets me the 'friens', but two times :S
$sqlQueryCat5 = mysql_query("SELECT friends.*,usuarios.alias AS nombre_amigo FROM friends LEFT JOIN usuarios ON friends.toid=usuarios.id AND friends.fromid='$this->id' ORDER BY id");
I don't know why.. and you?
thank you
It looks like you have another query that you are not showing here.
This query on its own only shows friends once, because friends.fromid='$this->id' means fromid can only be the id asked.
If your table ALWAYS contains [1,2] and [2,1] (both), then you only need to query one side to get the other.
SELECT friends.*,usuarios.alias AS nombre_amigo
FROM usuarios
INNER JOIN friends ON friends.fromid=usuarios.id
WHERE usuarios.id='$this->id'
ORDER BY id
Since your JOIN is not limiting the results of your query (as it is a LEFT JOIN and not an INNER JOIN), I'm guessing you want to move the friend limiter into your WHERE clause, like so:
$sqlQueryCat5 = mysql_query("SELECT friends.*, usuarios.alias AS nombre_amigo "
. "FROM friends "
. "LEFT JOIN usuarios ON friends.toid=usuarios.id "
. "WHERE friends.fromid=$this->id"
. "ORDER BY id");
Edit: looking at your query again, I'm guessing that you don't actually have a reason to use a LEFT JOIN - turn it into a regular JOIN and you could at the very least see a bit better performance.