Left join and show the non-foreign key - mysql

I have two tables that I'm joining, Users and Addresses.
The Users table has a unique (but not primary) key called userID.
The Addresses table has a primary key called userID.
I'm trying to left-join the tables so that I get all the info from the Users table regardless if it has a match in the Addresses table, so I used
select * from users u left join addresses a on a.userID = u.userID
This works, but it only shows userID's if there is a match. How do I get the userID regardless if there's a match or not?
Edit: The following image shows what my current query (left join) returns:

Now it's clear what the problem is.
There's nothing "wrong" with the query, except that it is returning multiple expressions (columns) with the same alias. And one of them is overriding the other. (Not in terms of the resultset being returned, all the columns and rows are there; the issue is with how your PHP script is processing the resultset. If you are referencing the values from the row by "association" (using the column name), only one of the column values gets referenced.
So, one way to fix that, is to qualify the columns in the query:
SELECT u.userID
, u.blah
, a.userID AS a_userID
, a.blah AS a_blah
FROM users u
LEFT
JOIN addresses a
ON ...
such that all column aliases are unique. Then all of those column names will be available by "association" in your PHP.

Using the query you provided should give a result in the u.userID column regardless of if it had a corresponding address. The a.userID column would only have data in the rows that were joined with an address.
You could change to:
select u.*, a.address from users u left join addresses a on a.userID = u.userID
Which would select only the relevant parts of the address and keep the whole u.

Related

Joining and querying two tables with conflicting column names

Imagine I have two tables: users and students
Each table has an id and email column. I want to be able to search for emails from both tables. I can join the two tables where the IDs match like this:
SELECT users.email,students.email as student_email FROM users
INNER JOIN students ON users.id = students.id
I can't search the email column because they have the same column name (email). So if I try use WHERE it complains that the column (email) is ambiguous. If I try use student_email it complains that the column doesn't exist.
If the two tables didn't use an identical column name (email) then it would be fine when I use WHERE.
The only solution I can think of is to get all rows and then loop around them and search the email strings manually. This is extremely slow compared to using MySQL like this:
SELECT users.email,students.email as student_email FROM users
INNER JOIN students ON users.id = students.id
WHERE email LIKE '%test#email.com%' OR student_email LIKE '%test#email.com%'
But of course this doesn't work because WHERE looks for the original column names before the SELECT.
How can I get around this without getting all the rows and the looping it? Maybe it is a union, rather than a JOIN? I'm not sure...
Just use the qualified column name. I also recommend table aliases:
SELECT u.email, s.email as student_email
FROM users u INNER JOIN
students s
ON u.id = s.id
WHERE u.email LIKE '%test#email.com%' OR
s.email LIKE '%test#email.com%';
Whenever you have more than one table in a query, you should always qualify all the column names. Using abbreviations for the tables as table aliases makes the query easier to write and to read.

MySQL Join statement to get data from two tables into a datagridview

I have two tables that I'm trying to join, 'holidays' and 'users'.
Users contains all my user info, the the column 'id' being primary and unique.
Holidays contains a column called 'userid', which corresponds to the id in the user table.
I'm struggling to get the join statement to work... what I'm looking for is the result of the select statement to give me the friendlyname (column 'fname' in user table) instead of giving me the value of userid.
Here's what I'm trying...
SELECT * FROM holidays JOIN users on users.id=holidays.userid WHERE holidays.status = 0
But i'm not getting a correct result - SQL executes without error, but my DGV is filled with tons of erroneous results.
Apologies If I have not used the correct terminology or whatever.
I'm new to the concept of joins.
Here is hopefully a better explanation of what I am after...
Thanks in advance.
You need to select the specific values you want from every table in the JOIN:
SELECT u.fname
FROM holidays h
JOIN users u
ON u.id = h.userid
WHERE h.status = 0
by the alias (FROM users u) you can select column from users table by u.fname
First try to right join to the User table. If you just want the fname then select the column name in the SELECT query, as SELECT * takes more time then SELECT column name.

How to select two tables and combined them together if null isn't present

Currently I can search two tables (events table and the users table) and combined them together using the following:
SELECT e.*, u.user_first_name, u.user_last_name
FROM users u, events e
WHERE e.event_user_id = u.user_id
ORDER BY e.event_id DESC
This will allow me to search everything from the events table and the first and last name from the users table.
But the problem occurs when the event_user_id can be NULL, meaning if there is a user set, I want to include their first and last name, but if there isn't then I just want that field to be blank.
SELECT e.*, u.user_first_name, u.user_last_name
FROM users u, events e
WHERE e.event_user_id = u.user_id
OR e.event_user_id IS NULL
ORDER BY e.event_id DESC
I know the above example isn't correct. My question is, how can I select two tables where the main table has an optional event_user_id, if it is not NULL, then combine with the users table to get the first and last name?
Is it just more reliable to have two separate queries?
As Ivan mentioned in the comments to my question, the correct way to successfully carry out the query I want is to use a left join, so I did a bit of research and I found the right query for me:
SELECT events.*, users.user_first_name, users.user_last_name
FROM events
LEFT OUTER JOIN users
ON events.event_user_id = users.user_id;
If event_user_id is present, then the user_first_name and user_last_name will be added to the row, however, if event_user_id is NULL then both the first and last name will also be NULL. Exactly what I wanted.

How to properly use inner join in SQL when I have to join a table twice?

Note: The actual schema isn't male/female, but some other criteria. I'm just using male/female for this example to make it easier to understand.
I have a table "users", which contains a column user_name and user_gender. The gender can be "M" or "F".
The problem is that I have another table, "messages", that has a column for "sender" and "receiver". These columns contains user_name in each row.
How can I use INNER JOIN so that I can get messages where only males send to females?
I know easily how to specify it once, binding users.user_name to "sender" or "receiver" but not both.
To expand on my question, how do see which top 10 pairs where a male sent the most messages to a female? Note, this means unique A/B pairs, so I want to return cases where a guy sends a single female a ton of messages, not when a guy spams a lot of messages to different females.
Think of your messages table as a "cross table" connecting two rows in the users table. When you join to a table like that, give users two different aliases, and refer to them in your join conditions, like this:
select *
from messages msg
join users m on msg.sender = m.user_id AND m.user_gender='M'
join users f on msg.receiver = f.user_id AND f.user_gender='F'
With this skeleton in hand, you should be able to figure out the rest of your query:
Use GROUP BY to group by m.user_id, f.user_id, and count(*) to count
Order by COUNT(*) to get the highest sender+receiver pairs at the top
Use LIMIT to grab the top ten pairs.

SQL Server 2005/2008 : find row values that exist and list that don't in my in select column condition IN()

I have a single table that contain columns:
UserID, EmployeeID, BadgeType, HiredDate, TermDate
Now I need to find userID that are with (gbro, qunro, 1utny, ybeiot, 4ybey)
The 3 users (gbro, qunro, 1utny) exist so it is listed with respective its column info.
What if ybeiot, 4ybey does not exist AT ALL but still I want them listed in a separate table still but with a message that PRINTS: User that does not exist: ybeiot;4ybey
Help, been finding way how to do this.
I tried JOIN (all the joins) but it does not result to what I wanted.
Did you look at SQL EXISTS keyword?
put all the users to be searched in a temp table or table variable #userstoSearch
select * from #userstoSearch us left join users u
on us.UserID=u.UserID where u.userID is not null
select us.UserID from #userstoSearch us left join users u
on us.UserID=u.UserID where u.userID is null
for xml path('')
You need two selects. The first will list the existing values and the second lists the not existing values. You should merge these results using the union keyword.