Relational query return null values - mysql

I have a question. In my database there are 2 tables. For example say:
Calendar table
uid
name
Signup table
uid
calendar_id
user_id
coming (-1 no, 0 undecided, 1 yes)
0 = undecided but not record is also undecided
User table
uid
name
And i want to see what users are coming to a specific event. So i have the query:
SELECT *
FROM user u, signup s
WHERE u.uid = s.user_id
AND s.event = 1
But this shows me all the users who have actually created a record in the database. I also want to see the users who don't have a record in the signup table. How can i achieve this?
Kind regards,

Don't use the old implicit join syntax any more. Use explicit joins. In your case - a left join
SELECT *
FROM user u
LEFT JOIN signup s ON u.uid = s.user_id
AND s.event = 1

Related

SQL matching IDs from different columns with their respective username

I have a table containing the columns user_id and lastreply_by_user_id and I'm looking for a way to match their columns with their username from the user table with id.
SELECT
table_threads.*,
table_users.username
FROM
threads AS table_threads
INNER JOIN users as table_users ON table_threads.user_id = table_users.id
OR table_threads.lastreply_by_user_id = table_users.id
WHERE
table_threads.category_id = :category_id
This is the code I have right now but this at the moment creates duplicate entries instead of one merged.
Just started with SQL recently and found the JOIN commands maybe it isn't the right one just point me in the right direction and I'll be thankful.
You need two joins to the same user table for that: one to connect by user_id, and one more to connect by lastreply_by_user_id. Use table aliases for disambiguation:
SELECT
t.*,
u.username as user_name,
r.username as last_reply_name
FROM
threads AS t
INNER JOIN users as u ON t.user_id = u.id -- actual user
INNER JOIN users as r ON t.lastreply_by_user_id = r.id -- reply user
WHERE
table_threads.category_id = :category_id

Join two tables query

I have two tables users and linkage. I am creating a link between one user to another. Means user A will be linked to user B and vise versa.
Now I want to get the details of linked users for a particular entered user_id. Means If user A is finding his linked Id's then the details of linked id's should be seen.
Linkage has three columns its id, user_id and linked_contact_id.
Users has columns as user_id, user_name,pass etc..
I tried one join but I only get the linked Id's from this not the details of id's.
SELECT * FROM Users INNER JOIN linkage ON linkage.user_id = Users.user_id WHERE linkage.linked_contact_id = 1
output
user_id linked_contact_id
1 4
1 1
1 5
How can I get this?Please help.. Thank you...
You will need to join on the users table a second time:
SELECT u.*, u2.* FROM Users u
INNER JOIN linkage l ON l.user_id = u.user_id
INNER JOIN Users u2 ON l.linked_contact_id = u2.user_id
WHERE l.linked_contact_id = 1
Please note that as you are selecting the same columns twice (in u.*, u2.*), you will probably have to list out each field with an alias to distinguish between them.
Something wrong on your ratio. But it's okay.
Try LEFT JOIN or RIGHT JOIN
SELECT * users
LEFT JOIN linkage
ON linkage.user_id = users.user_id
WHERE linkage.linked_contact_id = 1
Get Users information
SELECT users.*,
linkage.*,
contact.user_id as contact_user_id,
contact.user_name AS contact_user_name
FROM users
INNER JOIN linkage ON linkage.user_id = users.user_id
INNER JOIN users AS contact ON linkage.linked_contact_id = contact.user_id
WHERE linkage.linked_contact_id = 1
Edit
Here Screenshot of Query Output

mySQL SELECT help. IF or EXISTS?

I have this DB structure
* user
user_id
name
* client
client_id
name
* user_client
user_client_id
user_id
client_id
* message
message_id
client_id
description
If there are entries on user_client then the user has permissions restricted to the specific clients listed for his id on the table. If there are no entries, then the user has access to any client.
How can I select only messages that the user can read?
I'm trying to do an IF on the WHERE clause to check if any entries on the user_client table but I don't know where to go from there. It needs to select all messages from any client if no entries on user_client or only messages for client_id specified on user_client table
Thanks for the help!
I would suggest doing two different queries: one for the superusers and the other for the restricted users. Then you can join the two results with a UNION.
SELECT M.message_id,
M.client_id,
M.description
FROM message M
INNER JOIN user_client UC ON (UC.client_id = M.client_id)
INNER JOIN user U ON (UC.user_id = U.id)
WHERE U.id = :user_id
UNION
SELECT M.message_id,
M.client_id,
M.description
FROM message M
WHERE NOT EXISTS (
SELECT *
FROM user_client
WHERE user_id = :user_id
)
You can obtain the same result with other queries but IMHO this one is clearer and more maintainable.
Edit: If you want to ensure that the user exists you should join the second query with the user table.
SELECT M.message_id,
M.client_id,
M.description
FROM message M
JOIN user U
WHERE U.id = :user_id
AND NOT EXISTS (
SELECT *
FROM user_client
WHERE user_id = :user_id
)
One way the do this could be to use two different queries to create a set of the messages users can see and filter according to your needs; something like this should work:
select * from (
select u.user_id, u.name, c.name client, m.message_id, m.description
from user u
join user_client uc on u.user_id = uc.user_id
join client c on uc.client_id = c.client_id
join message m on c.client_id = m.client_id
union all
select u.user_id, u.name, c.name client, m.message_id, m.description
from user u
cross join client c
join message m on c.client_id = m.client_id
where user_id not in (select user_id from user_client)
) x
where x.user_id = 1;
Here users present in the user_client table are restricted to the set of messages that they have access to (the first set in the union), while users not present in the user_client table can see all messages (the second set in the union).
Sample SQL Fiddle
If I am understanding your question correctly, such as
1) Administrative user... They can look at EVERYTHING since they would have no records in the user_client table.
2) Client Supervisor... Such a person who's primary responsibility is to a specific client (or multiple clients). Therefore, the user DOES have a record in the user_client table. If so, then only allow the user to see records for those clients they DO have associations with.
select
m.message_id,
m.client_id,
m.description,
c.name as clientName
from
( select count(*) as HasClients
from user_client
where user_id = TheUserYouWant ) ClientCheck,
message m
left join user_client uc
on m.client_id = uc.client_id
AND uc.user_id = TheUserYouWant
join client c
on m.client_id = c.client_id
where
ClientCheck.HasClients = 0
OR NOT uc.user_id IS NULL
The query looks at the user_client table TWICE. The first time is to just get a count of those records that DO exist for the given user, regardless of which client associated with. The query will always come back with 1 row and it will either be 0 (no such records), or greater than 1 (however many they are associated with).
The second instance is a LEFT-JOIN to the user_client table, JUST IN CASE the person IS restricted to only looking at their own client messages.
The WHERE clause now comes in and says... if the underlying count of clients was zero, then ok to give me all messages. If any other value, then the user ID in the user_client table (as left-joined to the messages on both the CLIENT AND THE USER you want) MUST EXIST (via NOT a NULL value for the user_id column).
Now, you probably don't want to query EVERY message as it could get quite large as your database grows, but you could put whatever other criteria in the WHERE clause, such as date restrictions and/or client(s) you are interested in.

Select data from same field but in two different rows, then output to one row

I have a follow table that has follower and a followee fields that represents user_id in a user table. The user table has the names of the users, called full_name. I want to create a query that pushes an update from a post table to all followees when a follower posts. Results to to look like this:
user.full_name of followee, user.fullname of follower, update of followee.
Code I have is:
SELECT user.user_id, user.user_id, post.update
FROM follow
JOIN post ON post.user_id = follow.follower_user_id
JOIN user ON user.user_id = follow.followee_user_id
Where update.date > DATE_SUB(CURDATE(),INTERVAL 0 DAY)
GROUP BY follow.followee_user_id
It does the right query, but I can't get the follower name to populate. it just duplicates the followee. Any idea on how to write the select fields?
You need two joins on the user table - one for the follower and one for the followee:
SELECT followee_user.full_name AS followee_name,
follower_user.full_name AS follower_name,
post.update
FROM follow
INNER JOIN user AS followee_user
ON follow.followee_user_id = followee_user.user_id
INNER JOIN user AS follower_user
ON follow.follower_user_id = follower_user.user_id
INNER JOIN post ON follow.followee_user_id = post.user_id
WHERE post.update > DATE_SUB(CURDATE(), INTERVAL 0 DAY)
Note that you must provide aliases for each instance of the joined user table to disambiguate the two. In this case I have used "followee_user" and "follower_user".
I am not sure what update.date is so I have assumed it is a typo and you meant update; change this as necessary. Also the GROUP BY does not make any sense here so I have removed it.
You need to join to the user table two times, once for the follower role, and once for the followee role... something like this:
SELECT e.full_name AS followee_full_name
, r.full_name AS follower_full_name
, p.update
FROM follow f
JOIN post p ON p.user_id = f.follower_user_id
JOIN user r ON r.user_id = f.follower_user_id
JOIN user e ON e.user_id = f.followee_user_id
WHERE p.update_date > CURDATE() + INTERVAL 0 DAY

MySQL SQL command to query from one table with three same columns to another table

Sorry but I am not sure how to ask this question but I am working on a help desk application where I have tickets being created in one table. I also have another table that stores the users. My problem is with the tickets table, I have listed the user that created the ticket, the tech who will solve the ticket and a user that over sees the ticket. All three users reference the users table. So how do I can I query the tickets table and get all three users that reference the same table storing the users?
Table1: Tickets
1) Ticketnumber
2) EnteredBy User 100
3) Issue
4) FixedBy User 102
5) FixedByNotes
6) ResponsilbeUser User 103
Table2: Users
1) UserID
2) UserName
What I can do now is something like this:
Select Ticketnumber, EnteredBy, Issue, UserName FROM Tickets INNER JOIN Users
ON Tickets.EnteredBy = Users.UserID
Thanks Steve
You can extend current query to somewhat as follows:
Select Ticketnumber, Issue, Reporter.UserName, Developer.UserName, Manager.UserName FROM Tickets
INNER JOIN Users AS Reporter ON Tickets.EnteredBy = Reporter.UserID
INNER JOIN Users AS Developer ON Tickets.FixedBy = Developer.UserID
INNER JOIN Users AS Manager ON Tickets.ResponsibleUser = Manager.UserID
You need alias for joint tables if you want to get all names:
Select Ticketnumber, Issue, Informers.UserName, Fixers.UserName, Supervisors.UserName FROM Tickets
INNER JOIN Users Informers ON Tickets.EnteredBy = Users.UserID
INNER JOIN Users Fixers ON Tickets.FixedBy = Users.UserID
INNER JOIN Users Supervisors ON Ticket.ResponsibleUser = Users.UserID
WHERE...
Sorry as i am not able to understand your words, but if I assumed your need correctly.. just for a try this could help you..
if you need either of them i.e. all users who has either entered or fixed or saw an issue you can find by..
Select t.Ticketnumber, t.EnteredBy, t.Issue, u.UserID ,u.UserName FROM Tickets t
INNER JOIN Users u ON t.EnteredBy = u.UserID or t.FixedBy = u.UserID
or t.ResponsibleUser = u.UserID;
And If you need all users who has entered, fixed and saw an issue you can find by..
Select t.Ticketnumber, t.EnteredBy, t.Issue, u.UserID ,u.UserName FROM Tickets t
INNER JOIN Users u ON t.EnteredBy = u.UserID and t.FixedBy = u.UserID
and t.ResponsibleUser = u.UserID;