MySQL NOT IN return a wrong number - mysql

I have to clean a database with a lot of orphaned entries, on this case i have a table 3 tables
'Email' (69529 entries)
'ServiceHasEmail' (5782 entries)
'UserHasEmail' (26254 entries)
The two last tables reference the 'Email' table, so this table should have 26254 + 5782 (32036) entries.
I built a query to select all the entries on the 'Email' table which are not referenced on the UserHasEmail and ServiceHasEmail tables:
SELECT * FROM Email e
WHERE e.EML_Id NOT IN (SELECT EML_Id FROM ServiceHasEmail)
AND e.EML_Id NOT IN (SELECT EML_Id FROM UserHasEmail)
But this query returns me 40383 entries in place of 37493 (69529 - (26254 + 5782))
What i am missing here?

This can be because
tables ServiceHasEmail and UserHasEmail contains some emails
both.
tables ServiceHasEmail and UserHasEmail contains duplicates.
You can verify:
select count(distinct email) from Email
select count(distinct email) from ServiceHasEmail
select count(distinct email) from UserHasEmail
and
select count(distinct Email)
from
(select Email from ServiceHasEmail
union all
select Email from UserHasEmail
)
And your query should be
SELECT count(distinct Email)
FROM Email e
WHERE e.EML_Id NOT IN (SELECT EML_Id FROM ServiceHasEmail)
AND e.EML_Id NOT IN (SELECT EML_Id FROM UserHasEmail)

Looks like some ServiceHasEmail and UserHasEmail reference the same Email.

You could have EML_Id's, that are present both in ServiceHasEmail and UserHasEmail.
I suppose you have exactely 2,890 of them. Please try
SELECT * FROM `ServiceHasEmail` INNER JOIN `UserHasEmail` USING(`EML_Id`)
to verify this.

you can use the following query:
SELECT * FROM Email e
WHERE e.EML_Id NOT IN (SELECT EML_Id FROM ServiceHasEmail UNION SELECT EML_Id FROM UserHasEmail)

Related

Select 3 columns to one without union

I try to select three columns (TEXT - The same type) to one column without using union (System required), but I can't think on right way to do so.
select count(distinct(r)) as count
from (
select column1 as r from Table1
union all
select column2 as r from Table1
union all
select column3 as r from Table1
) a
This is the original query,
I tried to use CONCAT and COALESCE, but it isn't what I want.
I don't want to merge two string into one,
I want that all the select line will be in the same column.
For example - example - img
3 columns - to, cc and bcc (email recipients).
I want to know how much people I send emails.
Without double the emails (everyone can be on any column)
Thank you for your help!
I appreciate it.
Either use COUNT(DISTINCT ...):
SELECT COUNT(DISTINCT email) FROM (
SELECT DISTINCT firstColumn AS email FROM table
UNION
SELECT DISTINCT secondColumn AS email FROM table
UNION
SELECT DISTINCT thirdColumn AS email FROM table) AS Recipients
Even better: since you're running DISTINCT on the outer query, don't waste time doing that in your inner queries:
SELECT COUNT(DISTINCT email) FROM (
SELEC firstColumn AS email FROM table
UNION
SELEC secondColumn AS email FROM table
UNION
SELEC thirdColumn AS email FROM table) AS Recipients
See example fiddle here: http://sqlfiddle.com/#!9/edda57/10
No UNION, but even uglier. I join the table with itself and take the first 3*TABLE_LENGTH rows, because I need to process three different columns.
SELECT count(DISTINCT if(rank<=#size, recipient, if(rank<=2*#size,cc,bcc)))
FROM
(SELECT (#rank:=#rank+1) AS rank,
s1.recipient,
s1.cc,
s1.bcc
FROM sent AS s1
JOIN sent AS s2) AS multi,
(SELECT #rank:=0) AS dummy1,
(SELECT #size:=
(SELECT count(1)
FROM sent)) AS dummy2
WHERE rank <= 3*#size
Fiddle: http://sqlfiddle.com/#!9/14ac8a/14/0
Simply use alias into a concat :) example here :
SELECT CONCAT(to, cc, bcc, year) as new_colum_mailing FROM `mailing` .. WHERE ...

SQL - Get all rows of table one and count of rows

How do I create an SQL query which gets all the rows of the table and count of rows inserted under e-mail?
I tried something like this, but this groups the rows and so I don't get all the rows.
SELECT *, COUNT(email) AS 'count' FROM adverts GROUP BY email
select a1.*, a2.count
from adverts a1
join
(
SELECT email, COUNT(*) AS 'count'
FROM adverts
GROUP BY email
) a2 on a1.email = a2.email
try this,
select *,
(select count(Email)
from adverts where adverts.Email =a.Email) as EmailCount
from adverts as a
or this
SELECT *, COUNT(email) OVER (PARTITION BY email) as EmailCount FROM adverts

Count the number of occurrences of each email address

I have a mySQL workbench table called table_contacts, with the fields:
user_id and PrimaryEmail
I want to write a query that, for each row in the table will return:
User_id, PrimaryEmail and Number of occurrences of that email address in the table. So I want the following table to be returned:
I know I need to use a sub query. So far I have:
select user_id, PrimaryEmail,
(select Count(PrimaryEmail) from table_contacts where PrimaryEmail = table_contacts.PrimaryEmail)
from table_contacts
But this is returning the count of all email addresses in the table.
What am I doing wrong?
The solution of Simone and Grażynka will group by address, so you will lose some row each time the email address is more than one time.
To display all row with a count of same email, you can do :
SELECT t1.user_id, t1.PrimaryEmail, (SELECT COUNT(*) FROM table_contacts t2 WHERE t2.PrimaryEmail = t1.PrimaryEmail) FROM table_contacts t1
try this:
select user_id, PrimaryEmail, Count(PrimaryEmail)
from table_contacts
group by PrimaryEmail
in SQL tryit editor a similar query would be
SELECT customerid,count(country),country FROM [Customers] group by country
but in this case you receive only the count of each email (one row for each email). Other (better) solutions have been proposed if you want to list all the rows with the couunt added.
Try this one:
Select user_id, primaryemail, count(*)
from table_contacts
group by user_id, primaryemail
You need a group by, not a subquery
something like
select user_id, PrimaryEmail, Count(PrimaryEmail)
from table_contacts
group by PrimaryEmail
This should do the job:
select t1.user_id, t1.PrimaryEmail, count(*)
from table_contacts t1
join table_contacts t2 on t1.PrimaryEmail = t2.PrimaryEmail
group by t1.user_id, t1.PrimaryEmail
order by t1.user_id;

MySQL look for duplicates on multiple fields

I have a MySQL database with the following fields:
id, email, first_name, last_name
I want to run an SQL query that will display rows where id and email exists more than once.
Basically, the id and email field should only have one row and I would like to run a query to see if there are any possible duplicates
If you just want to return the id and email that are duplicated, you can just use a GROUP BY query:
SELECT id, email
FROM yourtable
GROUP BY id, email
HAVING COUNT(*)>1
if you also want to return the full rows, then you have to join the previous query back:
SELECT yourtable.*
FROM
yourtable INNER JOIN (
SELECT id, email
FROM yourtable
GROUP BY id, email
HAVING COUNT(*)>1
) s
ON yourtable.id = s.id AND yourtable.email=s.email
You'll want something like this:
select field1,field2,field3, count(*)
from table_name
group by field1,field2,field3
having count(*) > 1
See also this question.
You can search for all ids that meet a specific count by grouping them and using a having clause like this:
SELECT id, COUNT(*) AS totalCount
FROM myTable
GROUP BY id
HAVING COUNT(*) > 1;
Anything this query returns has a duplicate. To check for duplicate emails, you can just change the column you're selecting.

cross referencing records across tables

i have 10 similar tables in my database. all the tables have the same field email in them. i want to find out email addresses that occur in more than 3 tables. the field email is not a primary key.
Thanks in advance.
You could use a count function over a union all query:
SELECT email, COUNT(*) AS num_tables
FROM (SELECT DISTINCT email FROM table1
UNION ALL
SELECT DISTINCT email FROM table2
UNION ALL
-- All the other tables
) t
GROUP BY email
HAVING COUNT(*) > 1