MySQL users table: find rows that have the same email address - mysql

I have a users table in MySQL.
id | username | email
I would like to get the IDs of duplicated users based on the email address. So basically find the Ids of users where the email address can be found more than 1 times in the table.
I wrote something like this:
SELECT id
FROM users as users
WHERE (
SELECT count(id)
FROM users as users2
WHERE users.email = users2.email
) > 1
It works ok, but very slow, as the query doesn't seem to use the index. Any other ideas? Thanks!

The solution :
select u.id
from users as u
inner join
( SELECT email
FROM users
GROUP BY users.email
HAVING count(id) > 1
) as u2 on u2.email = u.email

Related

MySQL: Count how many times value in one column appears in another column

In my Database I have a user table which has one column with the User_ID and anther column with the path of the whole "tree".
user_id
promoter_path
1200
/200/840/780/1200
1785
/14/74/787/898/1047/1687/1785
2687
/2687
...
...
7847
/200/840/780/1200/5870/7847
...
...
If I want to know how many children the user_id 1200 has I do:
select
max(user_id) as name,
count(*) as c
FROM users
where promoter_path like '%1200%'
and I get
name
c
1200
2
So far it's easy.
But how can I do if I want a list for all ids?
Like
name
c
1200
2
1785
1
5550
5
10287
1
---
---
select max(u.user_id) as name,
(
select count(*) from users as u1 where promoter_path like u.user_id
) as c
from users as u
but this won't work.
Can you please help me?
Lose the max. You also want to add % around the user_id in like:
select u.user_id as name,
(
select count(*) from users where promoter_path like concat('%', u.user_id, '%')
) as c
from users as u
By the way OP, are you sure it shouldn't be:
select u.user_id as name,
(
select count(*) from users
where promoter_path like concat('%/', u.user_id, '/%')
or promoter_path like concat('%/', u.user_id)
) as c
from users as u
Because '/11200/something' like '%1200%' evaluates as true...
SELECT
u1.id, COUNT(u2.id)
FROM users u1 LEFT JOIN users u2
ON
u2.promoter_path LIKE concat('%/', u1.id, '/%')
OR pomoter_path like concat('%/', u.user_id)
GROUP BY
u1.id;
What this does, is:
pairs each user with users whose promoter_path includes their id (this could be event the same user)
counts how many users were paired with each user
the LEFT JOIN is important, so we get users with no matches as well.

MySQL delete data where field is contained in another table

I have a database with 2 tables like this (much larger than this)
users
Name | Email
Bill billy#gmail.com
Susan susan#gmail.com
-
bad_emails
Email
billy#gmail.com
bademail#gmail.com
I want to delete anything from users where the email is in the bad_emails table.
I tried something like this
DELETE FROM users WHERE (SELECT Email FROM bad_emails) as bad_emails = users.Email
But that's a syntax error, not sure on the correct syntax.
Multiple ways.
JOIN:
DELETE u
FROM users AS u
JOIN bad_emails AS b ON u.email = b.email
WHERE IN:
DELETE FROM users
WHERE email in (SELECT email FROM bad_emails)
WHERE EXISTS:
DELETE FROM users AS u
WHERE EXISTS (SELECT 1 FROM bad_emails AS b WHERE b.email = u.email)

How to get data from database with condition on another table where something exist or not

I have a table for users like this
id | name | password | email
1 saeid ***** asd#asd.com
I have another table called appointments
id | created_by | due_date | notification_send
1 1 ***** 0
I want to get all users from users table where they have at least created one appointment in the appointments table (denoted by created_by field in the appointments table).
I have tried the code below but it fails:
SELECT * FROM users LEFT JOIN appointments a ON persons.id = a.created_by
But obviously it does not work.
One way is to use the exists predicate:
SELECT * FROM users u
WHERE EXISTS (SELECT 1 FROM appointments a WHERE a.created_by = u.id)
Alternatively you could use an inner join, but the exists query corresponds better to your question in my opinion (that is if you only need data from the users table).
The left join says to get all rows from users regardless if they have matching rows in appointments which is not what you want.
You are searching for a match between the table and so I would suggest doing a INNER JOIN rather like below
SELECT * FROM users u
JOIN appointments a ON u.id = a.created_by
Also check your ON clause once I think either this is a typo or a big mistake. You are selecting from users table then why persons.id??
ON persons.id = a.created_by
Try something like this:
http://sqlfiddle.com/#!9/5eba3/2
select * from users c where (select count(*) from appointments where created_by = c.id) > 0;

select two logins from one record

I'm creating chat ( just for two people to chat, not "global" ) and my tables look like this:
MESSAGES:
id | author | receiver | content | sent
where author and receiver are id's from USERS:
id | login | avatar
and i want to get login and avatar both from receiver and author of the message. I was trying with something like this:
SELECT * FROM
((SELECT messages.*,users.login as starter,users.avatar FROM messages
LEFT JOIN users ON messages.author = users.id
WHERE messages.receiver = 1)
UNION
(SELECT messages.*,users.login as test,users.avatar FROM messages
LEFT JOIN users ON messages.receiver = users.id
WHERE messages.author = 1)
ORDER BY id DESC LIMIT 5) tmp
ORDER BY id ASC
and few other queries but i could only get one login ( either receiver or author ). Is there any way to do that?
Try this:
select * from messages m
join users a on (m.author=a.id)
join users r on (m.reciever=r.id)
Of course, you can add a where clause to filter it for a specific message, author or whatever.

basic join on mysql

I am having a hard time understanding joins on mySQL, and I cannot find any similar example to work with.
Suppose I have two tables: users and users_info.
in users I have id, email and password fields while, in users_info I have all their information, like name, surname, street, etc.
so, if I am getting a user like this:
SELECT * FROM users WHERE id = 43
and their information like this:
SELECT * FROM users_info WHERE id = 43
I will basically get 2 results, and 2 tables.
I understand now that I need to use join so that they are all together, but I just can't figure out out.
Any help?
It seems like both tables users and user_info are related with each others by the column id therefore you need to join them using this column like this:
SELECT
u.id,
u.email,
u.password,
i.name,
i.surname,
i.street
FROM users AS u
INNER JOIN user_info AS i ON u.id = i.id;
This will only select the fields id, email, ... etc. However, if you want to select all the columns from both the tables use SELECT *:
SELECT *
FROM users AS u
INNER JOIN user_info AS i ON u.id = i.id;
If you want to input the id and get all of these data for a specific user, add a WHERE clause at the end of the query:
SELECT *
FROM users AS u
INNER JOIN user_info AS i ON u.id = i.id
WHERE u.id = 43;
For more information about JOIN kindly see the following:
Join (SQL)From Wikipedia.
Visual Representation of SQL Joins.
Another Visual Explanation of SQL Joins.
Here's an example
SELECT * FROM users u
INNER JOIN users_info i
ON u.id=i.id
this means, you are joining users table and users_info table
for example
users
id name
---- -------
1 abc
2 xyz
users_info
id email
--- ------
1 abc#aaa.com
2 xyz#aaa.com
the query will return
id name email
--- ----- -------
1 abc abc#aaa.com
2 xyz xyz#aaa.com
Here's a nice tutorial
You can also do:
SELECT users.*, users_info.*
FROM users, users_info
WHERE users.id = users_info.id AND users.id = 43;
This means:
"Get me all the columns from the users table, all the columns from the users_info table for the lines where the id column of users and the id column of users_info correspond to each other"