Eliminate the duplicate rows from the table in SQL - mysql

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

Related

mysql probem on Leetcode

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;

SQL Query with COUNT, Having Count >1, display full details of duplicates

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

Find duplicates using MySQL considering multiple columns

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

Selecting newest distinct email address from table

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

Selecting across multiple tables with UNION

I reworked my database from one user table to multiple user tables (divided per role): tblStudents, tblTeachers, tblAdmin
When logging in, I didn't want to run three queries to check if the user exists somewhere in my DB. So what I did was put together the following query with union
select s.id as id, s.email as email, s.password as password, s.role as role from tblStudents s
union
select a.id as id, a.email as email, a.password as password, a.role as role from tblAdmin a
union
select t.id as id, t.email as email, t.password as password, t.role as role from tblTeachers t
This selects the fields that are the same across all tables and outputs the results nicely for me.
So, I decided to try this and for some reason, my login form wouldn't work. For my login form, I added a where clause which checks for the email address. I ran the query in my database app and surprisingly, when I do for example where email = "admin#admin.be" (this email exists in my database tblAdmin), it also selects a record from my students table.
With the where clause:
select s.id as id, s.email as email, s.password as password, s.role as role from tblStudents s
union
select a.id as id, a.email as email, a.password as password, a.role as role from tblAdmin a
union
select t.id as id, t.email as email, t.password as password, t.role as role from tblTeachers t
where email = "admin#admin.be"
The records both have id = 1 but I don't understand why it would select the student record when I'm filtering on the admin email address. Why is this? Can someone explain and provide me with a better solution to this problem? I basically have one login form and need to select across multiple tables to check if the user exists in my db.
Thanks for updating the query; now we can see that the WHERE condition is only applied to the last UNIONed query. You need to either add that WHERE clause to each query, or wrap it as a subselect and apply the WHERE clause to that.
select s.id as id, s.email as email, s.password as password, s.role as role from tblStudents s
where email = "admin#admin.be"
union
select a.id as id, a.email as email, a.password as password, a.role as role from tblAdmin a
where email = "admin#admin.be"
union
select t.id as id, t.email as email, t.password as password, t.role as role from tblTeachers t
where email = "admin#admin.be"
or
SELECT * FROM (
select s.id as id, s.email as email, s.password as password, s.role as role from tblStudents s
union
select a.id as id, a.email as email, a.password as password, a.role as role from tblAdmin a
union
select t.id as id, t.email as email, t.password as password, t.role as role from tblTeachers t
) foo where email = "admin#admin.be"
SELECT
R.co_C,
company3.Statuss
FROM
(
SELECT
company1.co_C
FROM
company1
UNION ALL
SELECT
company2.co_C
FROM
company2
) AS R
LEFT JOIN company3 ON R.co_C = company3.co_A;