Finding Non Matching ID - mysql

I have two tables, called "One" and "Two", they are both the same, table "One" has some IDs that are not there in Table "Two". but when i run this mysql Query, i can not get those non-matching values.
select count(bene) from one where bene not in (select bene from two);
And the result is Zero. so how do i get the non-matching values from Table one that are not there in table Two?

You can perform a left join and find only values that do not exist in second table. Below query is assuming that bene is your ID column:
SELECT one.*
FROM one
LEFT JOIN two ON one.bene = two.bene
WHERE two.bene IS NULL
or if you need just the count
SELECT COUNT(one.bene)
FROM one
LEFT JOIN two ON one.bene = two.bene
WHERE two.bene IS NULL
When performing a Left join you find all values in table one with corresponding values in table two. If there is no match all table two values will be NULL.
Then as a second step you use WHERE to filter only rows that have NULL for table two. This way you find all records in table one that do not have matching records in table two.

select count(*) from one a where not exists (select * from two b where a.bene=b.bene)

Related

naural join is giving Cartesian product of two relations

I have two relations, emp(id,name) and emp2(name,city,salary) with values:
and relation emp2 values :
As you can see, when I run natural join between them I get their Cartesian product.
But why, since they have a common attribute (name)?
You are getting natural join, not Cartesian product.
There is one copy of each common column and one copy of each column unique to an input table. There is a row for every different combination of a row from the left input table and a row from a right input table.
If a subrow value (('kim')) for common columns (name) appears n times in the left table (2 times) and m times in the right table (2 times) then it will appear n times m times in the output (2 times 2 times = 4 times).
An SQL Cartesian product would have columns name, city, salary, id & name and would have a row for every different combination of a row from the left input table and a row from a right input table.
That includes every possible combination of a name value from the left table and the right table. But for this example data there is only one name value over both tables, so every pair of name values has to have that value twice.
Natural join is the same as Cartesian product followed by restriction on equality of common columns followed by projecting away one of each common column followed by keeping distinct rows.
select * from emp inner join emp2 on emp.id = emp2.id
You have two time the same value in the common column (name) so this retrive the rows more time .
Your natural join is based on both the table that have not unique value each row.
Then in this case you get always more that a row for each entry (also with inner join) but you could solve using distinct
select dictinct emp.*, emp2.*
from emp
inner join emp2 on emp.name = emp2.name
or
select select dictinct emp.*, emp2.*
from emp2 natural join emp

Join more than two tables

I am trying to join 2 tables and in 1 table there may or may not have the corresponding values.but i need to join the table and list the fields as null.
I have tried to join the tables as left join.but If two entries is there in secoond table corresponding to the value of first table,then first table data is displayed twice.
I need to display only one time if there is two data in another table or there is no data in another table,but it should display as null.
Here is my sql query.
SELECT *,incident.incident_id as incidentid
FROM register_incident AS incident
LEFT JOIN incident_images AS im ON im.incident_id=
incident.incident_id
WHERE incident.state='Active'
I need to display only one time each data if there is no corresponding rows in another table,but the fields in the second table list as null.
If there is more than one row in another table,then also display each row in first table one time with one entry in the second table.
you can use select distinct for get only one row eg (limiting the select to indicent_id ,, but you can add the distinctcolumn you need ):
SELECT *,incident.incident_id as incidentid
FROM register_incident AS incident
LEFT JOIN (
select distinct incident_id from
incident_images
WHERE incident.state='Active' ) t ON t.incident_id= incident.incident_id

include null and zero in count() from related table

I would like to list in table (staging) the number of related records from table (studies).
So far this statement works well but returns only the rows where there are >0 related records:
SELECT staging.*,
COUNT(studies.PMID) AS refcount
FROM studies
LEFT JOIN staging
ON studies.rs_number = staging.rs
GROUP BY staging.idstaging;
How can I adjust this statement to list ALL rows in table (staging) including where there are zero or null related records from table (studies)?
Thank you
You have the tables in the wrong order in the LEFT JOIN:
SELECT staging.*, COUNT(studies.PMID) AS refcount
FROM staging LEFT JOIN
studies
ON studies.rs_number = staging.rs
GROUP BY staging.idstaging;
LEFT JOIN keeps everything in the first ("left") table and all matching rows in the second. If you want to keep everything in the staging table, then put it first.
And, in case anyone wants to complain about the use of staging.* with GROUP BY. This particular usage is (presumably) ANSI compliant because staging.idstaging is (presumably) a unique id in that table.

Why aren't these two result sets adding up?

I have a "master" table (cited_papers) of 144,194 rows, and a "sample" table (publication) that contains a sample of 7,977 of these rows. I am trying to get the rows (by their unique id field) that are in the master table but not the sample table:
SELECT DISTINCT c.*
FROM alex_WOS.cited_papers as c LEFT JOIN alex_WOS.publication USING (id)
WHERE alex_WOS.publication.id IS NULL
This works, but the result count I get is 141,019. Why aren't these counts adding up? (141,019 + 7977 != 144,194) I did a SELECT DISTINCT to count the rows in both the master and sample tables, so I am certain there are no duplicates in either of those tables.
The distinct may be throwing things off. Run the queries below to verify your numbers.
Verify the number of "master" rows:
SELECT count(*) FROM alex_WOS.cited_papers
Verify the number of "sample" rows:
SELECT count(*) FROM alex_WOS.publication
Verify the number of "master" rows not in "sample" table:
SELECT count(*) FROM alex_WOS.cited_papers c LEFT JOIN alex_WOS.publication p USING(id) WHERE p.id IS NULL
These numbers should add up...
As JNevill suggested, my sample table was not a subset of master after all. I'm a dummy...

SQL: Remove records from table A that don't exist in table B based on two fields

this is probably something simple but I can't wrap my head around it. I've tried IN, NOT EXISTS, EXCEPT, etc... and still can't seem to get this right.
I have two tables.
Table A
-----------
BK
NUM
Table B
------------
BK
NUM
How do I write a query to remove all records from table A, that are not in table B based on the two fields. So if Table A has a record where BK = 1 and NUM = 2, then it should look in table B. If table B also has a record where BK = 1 and NUM = 2 then do nothing, but if not, delete that record from table A. Does that make sense?
Any help is much appreciated.
You can do so
delete from tablea
where (BK,NUM) not in
(select BK,NUM from tableb)
using exists
delete from tablea a
where not exists
(select 1 from tableb where BK=a.BK and NUM = a.NUM)
Another alternative is to use an anti-join pattern, a LEFT [OUTER] JOIN and then a predicate in the WHERE clause that filters out all matches.
It's easiest to write this as a SELECT first, test it, and then convert to a DELETE.
SELECT t.*
FROM tablea t
LEFT
JOIN tableb s
ON s.BK = t.BK
AND s.NUM = t.NUM
WHERE s.BK IS NULL
The LEFT JOIN returns all rows from t along with matching rows from s. The "trick" is the predicate in the WHERE clause... we know that s.BK will be non-NULL on all matching rows (because the value had to satisfy an equality comparison, in a predicate in the ON clause). So s.BK will be NULL only for rows in t that didn't have a matching row in s.
For MySQL, changing that into a DELETE statement is easy, just replace the SELECT keyword with DELETE. (We could write either DELETE t or DELETE t.*, either of those will work.
(This is an illustration of only one (of several) possible approaches.)