Here is a question from LEETCODE.I don't know why my output is wrong. First I write the SELECT in the parenthesis to find out the repeated email address. Then I use the DELETE to filter out the repeated email address so anyone know what is wrong with my code? questionmycode
output
it is very simple. try this
-- Solution 1
with cte as
(
select id, email, Rank() OVER (partition by email order by id) ranks
from person where email in(
select email from person
group by email having count(email) >1
)
)
DELETE FROM person where id in
(
SELECT id FROM CTE where ranks!=1
)
-- Solution 2
DELETE p from person p
inner join (
select MIN(id) id, email from person
where email in(
select email from person group by email having count(email)>1
) group by email
) A On P.Id>A.id and p.email = a.email;
Related
I want to eliminate the duplicate rows based on email from the table and retrieve all the rows without duplicates.
I have tried using distinct but I'm not getting desired results.
SELECT
DISTINCT Email
FROM
Users
Example Table:
Id
Email
Username
1
sam#gmail.com
sam1122
2
john#gmail.com
john1122
3
sam#gmail.com
sam2233
4
lily#gmail.com
lily#as
What I want to retrieve:
Id
Email
Username
1
john#gmail.com
john1122
2
lily#gmail.com
lily#as
We can try using exists logic here:
SELECT Id, Email, Username
FROM Users u1
WHERE NOT EXISTS (
SELECT 1
FROM Users u2
WHERE u2.Email = u1.Email AND
u2.Id <> u1.Id
);
You can do it using left join :
select u.*
from Users u
left join (
select email, max(id) as Id
from Users
group by email
having count(1) > 1
) as s on s.email = u.email
where s.email is null;
Demo here
Yet another option, if you are using MySQL 8 -
SELECT Id, Email, Username
FROM (
SELECT *, COUNT(*) OVER (PARTITION BY Email) AS cnt
FROM Users
) t
WHERE t.cnt = 1;
SELECT Id, Email, Username
FROM Users
WHERE Email IN (
SELECT Email
FROM Users
GROUP BY Email
HAVING COUNT(*) = 1
)
SELECT id,
Email,
Username,
count(*) AS duplicate_email_count
FROM Users
GROUP BY Email
HAVING duplicate_email_count=1
I have a table like :
name employment_Status email
---- ---- -----
David E David#email.com
John U John#email.com
Michael E Michael#email.com
Steve E Michael#email.com
James U David#email.com
Mary U Mary#email.com
Beth E Beth#email.com
I started by selecting email and count(email):
SELECT email, COUNT(email) AS emailCount
FROM Table
GROUP BY email
HAVING ( COUNT(email) > 1 );
The problem occurred when I tried to include name as well:
SELECT name, email, COUNT(email) AS emailCount
FROM Table
GROUP BY name, email
HAVING ( COUNT(email) > 1 );
I would like to find all people with a duplicate email addresses, (only where both people are employed (E)). However it is returning zero results.
I'd like to be able to display all information for people with duplicate emails, and having employment_Status E. If two people have the same email, but one or both is Unemployed (U), then just ignore.
Could anyone advise?
I think you want exists:
select t.*
from t
where t.employeed = 'E' and
exists (select 1
from t t2
where t2.email = t.email and t2.employeed = 'E' and
t2.name <> t.name
);
Note that this assumes that name (or at least name/email) is unique.
In MySQL 8+, you can use window functions:
select t.*
from (select t.*, count(*) over (partition by t.email) as cnt
from t
where t.employeed = 'E'
) t
where cnt >= 2;
One way would be to use your query as a subquery in FROM clause, and JOIN the result with the main table.
SELECT t.*, d.emailCount
FROM (
SELECT email, employment_Status, COUNT(*) AS emailCount
FROM my_table
GROUP BY email
WHERE employment_Status = 'E'
HAVING emailCount > 1
) d
JOIN my_table t USING(email, employment_Status)
You could also use GROUP_CONCAT(name), if you are fine getiing the names in a (comma) separated string:
SELECT email, COUNT(*) AS emailCount, GROUP_CONCAT(name) as names
FROM my_table
GROUP BY email
WHERE employment_Status = 'E'
HAVING emailCount > 1
The result for your sample data would be:
email emailCount names
-----------------------------------------------
Michael#email.com 2 Michael,Steve
I need to find duplicate uses based on either same email OR first_name, last_name combination OR same birth_date. What I could comfortably try was:
SELECT id, first_name, last_name
FROM users
where id IN (SELECT id
from users
GROUP BY email
HAVING count(*) > 1)
GROUP BY email, id;
The above gives only duplicate email details, but I'm bit confused about handling other conditions based on first_name, last_name combination OR same birth_date as well.
Is it possible to achieve it in a single query?
Try doing a UNION of three separate queries which checks for the three duplicate criteria:
SELECT id
FROM users
GROUP BY id
HAVING COUNT(DISTINCT email) > 1
UNION
(
SELECT id
FROM users t1
INNER JOIN
(
SELECT firstname, lastname
FROM users
GROUP BY firstname, lastname
HAVING COUNT(*) > 1
) t2
ON t1.firstname = t2.firstname AND
t1.lastname = t2.lastname
)
UNION
SELECT id
FROM users
GROUP BY id
HAVING COUNT(DISTINCT birthdate) > 1
I use to do
SELECT email, COUNT(email) AS occurences
FROM wineries
GROUP BY email
HAVING (COUNT(email) > 1);
to find duplicates based on their email.
But now I'd need their ID to be able to define which one to remove exactly.
The second constraint is: I want only the LAST INSERTED duplicates.
So if there's 2 entries with test#test.com as an email and their IDs are respectively 40 and 12782 it would delete only the 12782 entry and keep the 40 one.
Any ideas on how I could do this? I've been mashing SQL for about a hour and can't seem to find exactly how to do this.
Thanks and have a nice day!
Well, you sort of answer your question. You seem to want max(id):
SELECT email, COUNT(email) AS occurences, max(id)
FROM wineries
GROUP BY email
HAVING (COUNT(email) > 1);
You can delete the others using the statement. Delete with join has a tricky syntax where you have to list the table name first and then specify the from clause with the join:
delete wineries
from wineries join
(select email, max(id) as maxid
from wineries
group by email
having count(*) > 1
) we
on we.email = wineries.email and
wineries.id < we.maxid;
Or writing this as an exists clause:
delete from wineries
where exists (select 1
from (select email, max(id) as maxid
from wineries
group by email
) we
where we.email = wineries.email and wineries.id < we.maxid
)
select email, max(id), COUNT(email) AS occurences
FROM wineries
GROUP BY email
HAVING (COUNT(email) > 1);
delete from wineries
where id not in
(
select * from
(
select min(id)
from wineries
group by email
) x
)
You need a subquery to trick MySQL to delete from a table it is selecting from at the same time.
DELETE duplicates.*
FROM wineries
JOIN wineries AS duplicates USING (email)
WHERE duplicates.id < wineries.id;
play with it on sqlfiddle.com
This is the simplest option:
DELETE FROM wineries
WHERE id NOT IN
(
SELECT MIN(id) id
FROM wineries
GROUP BY email
);
This will only keep the first inserted record for each email address, all other records will be deleted. Credit for this answer should go to #juergen d since this is just a revised version of his answer.
Very quick one:
I've done this before, but having a bit of a mind blank right now.
SELECT max(id) as id, username, email
FROM user_info
WHERE username!=''
GROUP by id,email
Unfortunately this is not working. It will select the max id but not then the corresponding data from that row.
If you have multiple ids per email address, then you can use max(id) and group by the email only.
SELECT max(id) as id, username, email
FROM user_info
WHERE username <> ''
GROUP by email, username
You can use a subquery which will return the max id in the subquery and then you use that to self join on the table to return the most recent id, username and email:
SELECT u.id, u.username, u.email
FROM user_info u
INNER JOIN
(
select max(id) maxid, email
from user_info
where username <> ''
group by email
) u2
on u.id = u2.maxid
See SQL Fiddle with Demo
Select DISTINCT(email), MAX(id)
FROM user_info
GROUP by email
ORDER BY id DESC