MySQL: Selecting duplicates among many fields - mysql

I am using the following query to select emails that are duplicates:
SELECT email
FROM contacts
WHERE active = 1
GROUP BY email
HAVING ( COUNT(email) > 1)
In the case above, if two users have the same email, that query will show them. However, there is another email field named email2, what can I do so that I compare the count among many email fields? (So, for example, if a user has email equal to email2 of another user, they will be considered duplicates)
Thank you!

SELECT tmp.email FROM (
SELECT email as email FROM contacts WHERE active = 1
UNION ALL
SELECT email2 as email FROM contacts WHERE email != email2 AND active = 1
) as tmp
GROUP by tmp.email
HAVING COUNT(tmp.email) > 1
P.S : my syntax could be wrong, but the idea should be something like this.

SELECT email
FROM contacts
WHERE (email = email2) AND (active = 1)
if I'm interpreting you correctly. Or do you mean that some user records may have "user#example.com" in the email field in one record, and the same address in the email2 field in another record? that'd be
SELECT primary.email, primary.id, secondary.id
FROM contacts AS primary
INNER JOIN contacts AS secondary ON (primary.email = secondary.email2)

Related

How do I update one column value to contain all of the value in two columns of a table in MySQL?

I am a college student currently studying SQL attack and prevention. There is an exercise where we need to
Update your first_name to be the email and password of all users who is
an admin (assume that there is a field in the users table called
is_admin where it's 0 if the user is not an admin, or 1 if the user is
an admin).
This way, when you log out and log back in, instead of saying Welcome
[your first_name], it would say Welcome [whatever was stored in
first_name field].
Lets assume that there is 6 row in my users table and that my id is 6
I tried to use group concat for email and password
SELECT group_concat(email, " ", password)
AS account_information FROM users
WHERE is_admin = 1
So far it works, it returned 1 row with all of the email and password of users who are an admin and I thought that this is the code I should subquery to be set for my first_name. And now I subqueried it to update my first_name with this code.
UPDATE users
SET first_name = (SELECT group_concat(email, " ", password) AS account_information
FROM users
WHERE is_admin = 1)
WHERE id = 6
I got an error 1093: saying that I can't specify target table 'users' for UPDATE in FROM clause
Can someone help me with this exercise?
Use a CROSS join of the table to a query that returns the concatenated values:
UPDATE users u
CROSS JOIN (SELECT GROUP_CONCAT(email, ' ', password) new_name FROM users WHERE is_admin = 1) t
SET u.first_name = t.new_name
WHERE u.id = 6;

mysql GROUP BY query showing partial matches in email field

I have the following query for finding duplicate email addresses in mysql db .
It's returning partial match duplicate values , how can get only exact matches ?
SELECT id, email, date FROM mytable GROUP BY email HAVING COUNT(email) > 1
For example its giving following results:
1234567890#foo.net
1234567890#bar.net
or
123#foo.com
456#foo.com
or
100abc#gmail.com
100xyz#foo.com
100xhsy#bar.com
#Abey I do this by joining the table into itself on the field I want to show is identical but where a truly unique value (like id) is different between the two records.
Here is how you would do that:
SELECT `mt1`.`id`,
`mt1`.`email`,
`mt1`.`date`
FROM `mytable` AS `mt1`
JOIN `mytable` AS `mt2` ON `mt2`.`email` = `mt1`.`email`
AND `mt2`.`id` <> `mt1`.`id`
GROUP BY `mt1`.`id`
If you want to have a distinct list of the duplicate emails and don't care to see each individual record, just trim out the other fields you are returning like this:
SELECT `mt1`.`email`
FROM `mytable` AS `mt1`
JOIN `mytable` AS `mt2` ON `mt2`.`email` = `mt1`.`email`
AND `mt2`.`id` <> `mt1`.`id`
GROUP BY `mt1`.`email`
Here is an example mocked up in sqlfiddle.
Hope this helps!

MySQL if result null change query

what if I have two strings: "123" and "abc". I want to select username if there's username "123" then choose it, if not found (null) then select username where "abc"
I have a table called USERS, this table responsibility with workflow engine account. I want to show columns in USERS:
username
email
usr_firstname
usr_lastname
I am using concat to merge column 3 and 4 with space between it. In the office, there are 2 types of employee:
origin/internal employee
outsource/partner employee
Origin employee login into every system using LDAP (FirstName.LastName), but outsource or partner employee login individually just for our workflow engine using employee identity number.
In this case, if I use something like:
Where username = 'employeenumber' or username = 'LDAPacc' the result is both account (used and unused for outsource) they appear. I want to show just 1 rows and 1 query but it's work with internal or even outsource (they will got data correctly for outsource).
You can use like this query;
SELECT *
FROM TABLE
WHERE username IN ('123', 'abc')
AND (username='123' OR NOT EXISTS(SELECT * FROM TABLE WHERE username='abc'))
You could use COALESCE.
COALESCE selects the first non null value out of the ones supplied.
So you could use....
SELECT COALESCE(String_123, string_ABC);
If string_123 has a value it will select that, otherwise it will select string_ABC unless of course they are both null.
So to be safe include a default value.......
SELECT COALESCE(String_123, string_ABC, string_Default);
I've found when I tested my logic to mysql tryit editor by w3schools and It's worked properly what I need. Here's my query:
SELECT * FROM Customers WHERE CustomerID = 'zz' OR (NOT EXISTS (SELECT * FROM Customers WHERE CustomerID = 'zz') AND CustomerID = '3')
let's say CustomerID is equivalent to my username column, then I tried to swap 'zz' and '3' value and it's still works. I hope there's more simple query than this

SQL where not in LIKE

I have a list of email addresses in one table and a list of domains in another table. I want to query the email from the email table ONLY if their email doesn't have a domain set in the domains table.
email domains
------ -------
a#google.com yahoo.com
a#yahoo.com ebay.com
a#ebay.com
a#gmail.com
So only a#google.com and a#gmail.com should be the result of the query.
The issues im running into is I have about 6 million rows in the emails table and it is taking substantially long to query even with proper indexes. Is there a better way to go about this? I also have a feeling using concat isn't helping because when you use a function it doesn't use indexes anymore?
Here is my query:
SELECT
email
FROM
emails
LEFT JOIN `domains` ON emails.email LIKE CONCAT( '%', domains.domain, '%' )
WHERE
AND `domains`.`domain` IS NULL
I would use a subquery like this:
select e.*
from email e
where not exists (select 1
from domains d
where e.email like concat('%', d.domain)
);
However, you might be able to get better performance with this version:
select e.*
from email e
where not exists (select 1
from domains d
where substring_index(e.email, '#', -1) = d.domain
);
The equality may make it possible to use an index on domains(domain).

SQL Preferred column

I have a MySQL table that keeps details about people, for example:
Name
Address
WorkEmail
HomeEmail
Preferred Email ('WorkEmail' or 'HomeEmail')
I want to select their preferred email only. Is there a neat way to do this using SQL? or will I just need to do this after I pull out the data?
A simple case statement should do the trick:
SELECT
Name,
CASE WHEN PreferredEmail = 'WorkEmail' THEN WorkEmail ELSE HomeEmail END AS Email
FROM
MyTable
(Select WorkEmail from MyTable where preferredEmail = 'WorkEmail')
Union
(Select HomeEmail from MyTable where preferredEmail = 'HomeEmail')
select IF(PreferredEmail = 'WorkEmail', WorkEmail, HomeEmail) AS Email
Why do you need a list of more than one email? If you are collecting multiple email address and you may at sometime want to collect more than one you could always create a secondary table that would associate the user with all of their possible email addresses and have a second third column that could be a flag to signify the Primary email.
Main Table
- UID
- Name
- Address
Email table
- UID
- Email address
- Primary
Then you could just do a query for where Primary is flagged and join to the other on the Unique ID.