I have a users table and an edits table (showing who performed changes on their own or someone else's profile).
In the edits table, the editor and editee are listed using their userid, which is the unique id in the users table.
I would like to create the query:
Select users.username (the editee), users.username (the editor) from users
inner join edits on users.id = edits.editee_id
How would I create a subquery to pull the editor's name?
Thanks
You need to join the users table twice.
SELECT whatever,
editor.username AS editor_username,
editee.username AS editee_username
FROM edits
JOIN users AS editor ON edits.editor_id = editor.id
JOIN users AS editee ON edits.editee_id = editee.id
See what's going on? You use the users table twice, and give it a different alias in each use.
Related
I am assigning unique users to vouchers on my website.1 user may have more than one voucher assigned to them but cannot be assigned the same voucher twice.I have 2 mysql tables that I am fetching data from.
tbl_users
tbl_voucher_users
When a user click on a button on my website, they pass along a voucher_id with which I use to display eligible users that can be assigned this voucher ( I.e Users that have not been assigned to this voucher ).
Below is how I am getting the users where voucher_id = 8
$user_data = DB::table('users')
->leftJoin('voucher_users', 'users.id', '=', 'voucher_users.user_id')
->where('voucher_users.voucher_id','!=',8) //User not assigned this voucher
->select('users.*','users.id as userID','voucher_users.*')
->get();
My problem
I am able to left join without the where clause and get results from both Users table and Voucher_users table having eliminated all users assigned voucher_id=8.
However, the results also include users who are assigned other vouchers but also the voucher I am assigning.
i.e
Expected resulsts would be users: 8,11,12,13,14 having eliminated users: 1,4
But my current results are:4,8,11,12,13,14
How do I get rid of the user 4 to prevent double assignment?
Thanks to the suggestion above by #Kevin Lynch to use NOT EXIST .. I simplified the code to:
SELECT users.*
FROM
users
WHERE
NOT EXISTS(SELECT user_id FROM voucher_users WHERE voucher_users.user_id = users.id AND voucher_id=9)
It works so far, I can then covert it to Laravel style
NOT EXISTS would be a good solution if this were to remain a small project (or if you could put more constraints on the users to keep the dataset small perhaps by limiting based on user created date or similar).
However if you can't do such a thing, this query will eventually give you problems because under the hood, mysql will be running that sub-query for each record returned in the main query. You can check https://dev.mysql.com/doc/refman/5.6/en/subquery-materialization.html for more information.
A different solution which would handle the scaling quite a bit better would be to generate a temporary table of users that have the voucher you are looking to remove...
create temporary table tmp_voucher_user (user_id int not null, primary key (user_id)) as
select distinct user_id from voucher_users where voucher_id = 8;
Now that we have a table of users we which to remove, all we need to do is worry about a simple left join...
select users.*, user_voucher.*
from users
inner join user_voucher on users.id = user_voucher.user_id
left join tmp_voucher_user on users.id = tmp_voucher_user.user_id
where tmp_voucher_user.user_id is null -- this part is important, it's only going to grab users where there isn't a match on tmp_user_voucher
Unfortunately this isn't as clean as just doing a NOT EXISTS and I don't believe Laravel supports a way to build temporary tables outside of just writing a raw query but it should scale quite a bit better.
I'm looking for a way to select users from a user table that have at least one relating entry in another table. Probably my join approach is totally wrong but that is what I was trying and should give you an idea of the structure:
SELECT users.`id`, users.`email`, users.`username`, users.`status`, users.`date_reg`
FROM dir_editors as users
JOIN dir_links as links ON (links.`id_editor` = users.`id`)
WHERE COUNT(links.`id_editor`) > 1
So the goal is to get all these user data from user that have at least one link entry in the dir_links table where the id_editor is the field in the dir_links table.
Thanks for helping
SELECT users.`id`, users.`email`, users.`username`, users.`status`, users.`date_reg`
FROM dir_editors as users
WHERE EXISTS(SELECT 1 FROM dir_links as links WHERE links.`id_editor` = users.`id`)
SELECT users.`id`, users.`email`, users.`username`, users.`status`, users.`date_reg`
FROM dir_editors as users
JOIN dir_links as links ON (links.`id_editor` = users.`id`)
Remove this WHERE COUNT(links.id_editor) > 1 because this imposing condition.
INNER JOIN: Returns all rows when there is at least one match in BOTH tables
An INNER JOIN selects the records that are found in both tables, depending on a key that you put in your ON statement:
SELECT users.id, users.email, users.username, users.status, users.date_reg
FROM dir_editors AS users
INNER JOIN dir_links as links
ON links.id_editor = users.id
I am trying to find out how to find the emails that do not exist in a table using the emails from the conditional.
I could create a table with these emails but that seems like overkill for what I need it for.
What I am looking for is a query that would show me the conditional value and NULL as the user ID.
Is this possible?
I have a query like this:
SELECT u.uid, u.mail
FROM `users` u
WHERE u.mail IN (
'alot#of',
'emails#that',
'ineed#tofind',
)
This works great at finding the emails and associating the user id. Now I need to identify which emails do not exist in the result. I am currently only using 56 emails and 6 do not appear in the list. I am trying to identify which emails are not found.
NOT IN won't work as I have over 40,000 users. I only want to identify the emails not found from my conditional. I have 56 emails and only 50 results. I need to identify the 6 not found (they may not even be in the table at all)
Let me attempt to clarify this a little more:
I am given a list of emails for supposed accounts in the system. I am trying to find the accounts from the given email. This part is fine. Now, the issue I am having, I was given 56 emails but only 50 were found. I need to identify which emails out of the 56 were not found. The emails are all thrown into the conditional. NOT IN won't work because it would return all user but the 50 that were found. (roughly 40,000) I just need to identify the emails from the conditional that were not found in the table.
Thanks for any insight or suggestions to do what I need.
There isn't a way to do what you want without creating some additional items to track the emails. Basically, you're trying to get MySQL to tell you which items in the WHERE portion aren't found, but MySQL can only tell you about rows in a table.
You need to make a secondary table that stores the email addresses from your list, call it list. I would make it a single column table with just the emails. Then LEFT JOIN it against the users table and find where the uid is null.
SELECT u.uid, l.mail
FROM `list` l
LEFT JOIN `users` u ON u.mail=l.mail
WHERE u.uid IS NULL
As posted in the comments, NOT IN may be helpful. But there are also other ways. One of them is to left join your table with the result of your query and show only non-coincident rows:
select u.uid, u.mail
from users as u
left join (
select u.uid, u.mail
from users
where mail in ('alot#of','emails#that','ineed#tofind')
) as a on u.uid = a.uid
where a.uid is null;
Add the fields you need to the join (if uid is not enough)
So your question now becomes more complicated... you want to find all the E-Mails in your condition that are not found in your table.
As far as I know, there's not a simple SQL sentence that will give you that... but you can work with temp tables and get it. The solution implies:
Create a temporary table to hold the values you want to search (and add the appropriate indexes to it)
Insert the values you want to search
Execute a select query to find non-matching rows
So... let's do it:
-- 1. Create a temp table to hold the values
drop table if exists temp_search_values;
create temporary table temp_search_values (
mail varchar(100),
unique index idx_mail(mail) -- Don't allow duplicate values here
);
-- 2. Insert the search values
insert into temp_search_values (mail) values
('alot#of'),('emails#that'),('ineed#tofind');
-- 3. Execute the query
select a.*
from users as u
left join temp_search_values as a on u.mail = a.mail
where u.mail is null;
Remember: Temporary tables are only visible to the connection that created them, and are deleted when the connection is closed or killed.
NULL is a strange result. It's not true and it's not false. If you want to check for it, you have to look specifically.
SELECT u.uid, u.mail
FROM `users` u
WHERE u.mail NOT IN (
'alot#of',
'emails#that',
'ineed#tofind',
) and u.uid IS NULL
* Oh, I see what you're getting at. This will work, although it's not pretty. *
select * from
(SELECT 'emails#that' as v
UNION SELECT 'alot#of' as v,
UNION SELECT 'ineed#tofind' as v
) as test
left join users on u.mail = test.v
where u.uid is null
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.
I have two tables. One is a table of users with a unique id field, and the other is a table of data, with a column that holds the user id of whoever generated that piece of data.
I want to do something like SELECT data,genned_by FROM datatable; but I want to replace the results for genned_by with SELECT username FROM users WHERE id = genned_by
So that the results from the query changes the userid into a username that corresponds with the other table.
I did some research and figured INNER JOIN might be what I'm looking for, but I'm left very unsure of how to use it after reading it. Help?
Try to use
SELECT d.data, u.username FROM database d INNER JOIN user u ON u.id=d.genned_by
Hope it helps you
SELECT datatable.data,users.username
FROM datatable, users
WHERE users.id = datatable.genned_by