Reputation: 17608
table1 (id, name)
table2 (id, name)
Query:
SELECT name
FROM table2
-- that are not in table1 already
Upvotes: 763
Views: 1560399
Reputation: 2200
For MariaDB, one of the fields I was selecting was very large. And there were millions of records. By removing that field the query ran exponentially faster. To get the field anyway, I ran the following. Table a
and aa
are the primary table. tableb
is the one with matching records that we don't want:
SELECT aa.id, aa.field1, aa.field2, aa.large_field FROM (
SELECT tablea.id
FROM tablea
LEFT JOIN tableb
ON tableb.parent_id = tablea.id
WHERE tableb.id IS NULL
) as a INNER JOIN tablea as aa ON a.id = a.id;
I am not sure why the down vote. The inner query could work on it's own to get records in tablea that are not in tableb:
SELECT tablea.id
FROM tablea
LEFT JOIN tableb
ON tableb.parent_id = tablea.id
WHERE tableb.parent_id IS NULL
Upvotes: 0
Reputation: 119
I tried all solutions above but they did not work in my case. The following query worked for me.
SELECT NAME
FROM table_1
WHERE NAME NOT IN
(SELECT a.NAME
FROM table_1 AS a
LEFT JOIN table_2 AS b
ON a.NAME = b.NAME
WHERE any further condition);
Upvotes: 0
Reputation: 543
All the above queries are incredibly slow on big tables. A change of strategy is needed. Here there is the code I used for a DB of mine, you can transliterate changing the fields and table names.
This is the strategy: you create two implicit temporary tables and make a union of them.
Seems not elegant, but it is orders of magnitude faster than all the above solutions.
IMPORTANT NOTE: enable the INDEX on the columns to be checked.
SELECT name, source, id
FROM
(
SELECT name, "active_ingredients" as source, active_ingredients.id as id
FROM active_ingredients
UNION ALL
SELECT active_ingredients.name as name, "UNII_database" as source, temp_active_ingredients_aliases.id as id
FROM active_ingredients
INNER JOIN temp_active_ingredients_aliases ON temp_active_ingredients_aliases.alias_name = active_ingredients.name
) tbl
GROUP BY name
HAVING count(*) = 1
ORDER BY name
Upvotes: 5
Reputation: 530
You can use following query structure :
SELECT t1.name FROM table1 t1 JOIN table2 t2 ON t2.fk_id != t1.id;
table1 :
id | name |
---|---|
1 | Amit |
2 | Sagar |
table2 :
id | fk_id | |
---|---|---|
1 | 1 | [email protected] |
Output:
name |
---|
Sagar |
Upvotes: 4
Reputation: 192
First define alias of table like t1
and t2
.
After that get record of second table.
After that match that record using where
condition:
SELECT name FROM table2 as t2
WHERE NOT EXISTS (SELECT * FROM table1 as t1 WHERE t1.name = t2.name)
Upvotes: 4
Reputation: 2137
I don't have enough rep points to vote up froadie's answer. But I have to disagree with the comments on Kris's answer. The following answer:
SELECT name
FROM table2
WHERE name NOT IN
(SELECT name
FROM table1)
Is FAR more efficient in practice. I don't know why, but I'm running it against 800k+ records and the difference is tremendous with the advantage given to the 2nd answer posted above. Just my $0.02.
Upvotes: 186
Reputation: 31
See query:
SELECT * FROM Table1 WHERE
id NOT IN (SELECT
e.id
FROM
Table1 e
INNER JOIN
Table2 s ON e.id = s.id);
Conceptually would be: Fetching the matching records in subquery and then in main query fetching the records which are not in subquery.
Upvotes: 3
Reputation: 2763
SELECT <column_list>
FROM TABLEA a
LEFTJOIN TABLEB b
ON a.Key = b.Key
WHERE b.Key IS NULL;
https://www.cloudways.com/blog/how-to-join-two-tables-mysql/
Upvotes: 101
Reputation: 89
I'm going to repost (since I'm not cool enough yet to comment) in the correct answer....in case anyone else thought it needed better explaining.
SELECT temp_table_1.name
FROM original_table_1 temp_table_1
LEFT JOIN original_table_2 temp_table_2 ON temp_table_2.name = temp_table_1.name
WHERE temp_table_2.name IS NULL
And I've seen syntax in FROM needing commas between table names in mySQL but in sqlLite it seemed to prefer the space.
The bottom line is when you use bad variable names it leaves questions. My variables should make more sense. And someone should explain why we need a comma or no comma.
Upvotes: 3
Reputation: 83143
You can either do
SELECT name
FROM table2
WHERE name NOT IN
(SELECT name
FROM table1)
or
SELECT name
FROM table2
WHERE NOT EXISTS
(SELECT *
FROM table1
WHERE table1.name = table2.name)
See this question for 3 techniques to accomplish this
Upvotes: 360
Reputation: 211
Here's what worked best for me.
SELECT *
FROM @T1
EXCEPT
SELECT a.*
FROM @T1 a
JOIN @T2 b ON a.ID = b.ID
This was more than twice as fast as any other method I tried.
Upvotes: 21
Reputation: 1076
That work sharp for me
SELECT *
FROM [dbo].[table1] t1
LEFT JOIN [dbo].[table2] t2 ON t1.[t1_ID] = t2.[t2_ID]
WHERE t2.[t2_ID] IS NULL
Upvotes: 8
Reputation: 41867
SELECT t1.name
FROM table1 t1
LEFT JOIN table2 t2 ON t2.name = t1.name
WHERE t2.name IS NULL
Q: What is happening here?
A: Conceptually, we select all rows from table1
and for each row we attempt to find a row in table2
with the same value for the name
column. If there is no such row, we just leave the table2
portion of our result empty for that row. Then we constrain our selection by picking only those rows in the result where the matching row does not exist. Finally, We ignore all fields from our result except for the name
column (the one we are sure that exists, from table1
).
While it may not be the most performant method possible in all cases, it should work in basically every database engine ever that attempts to implement ANSI 92 SQL
Upvotes: 1292
Reputation: 1816
You can use EXCEPT
in mssql or MINUS
in oracle, they are identical according to :
Upvotes: 10
Reputation: 181
Watch out for pitfalls. If the field Name
in Table1
contain Nulls you are in for surprises.
Better is:
SELECT name
FROM table2
WHERE name NOT IN
(SELECT ISNULL(name ,'')
FROM table1)
Upvotes: 18
Reputation: 1490
This is pure set theory which you can achieve with the minus
operation.
select id, name from table1
minus
select id, name from table2
Upvotes: 53