Reputation: 147
Say I have a table people
with a name
field.
In that table are 3 rows with names: Steve, Mark, Ricky
Then I have a list of names: [Shane, Ricky, Mark]
I want to execute one query that will return the values that aren't already in the table.
I know I can do this with the following:
names = [Shane, Ricky, Mark]
for name in names:
sql = '''SELECT * FROM people WHERE name=%s'''
db.execute(sql, args=name)
results = db.fetchall()
# If no results are returned for a name
# this means the name isn't already in the table.
if not results:
print(name) # This would return 'Shane' as it's not already in the table.
Is there a way I could do this more efficiently with one SQL statement, rather than looping over each name in the list?
Upvotes: 0
Views: 1201
Reputation: 35343
UNTESTED:
Generate the list as a table (t1) and then return from that generated table, those values not in your people table.
The issue is a database can't return values that don't exist. So we first create a temporary table with your values so they exist and can be returned. Then we rub it up against the people table to find those that don't exist; thus allowing us to return those names not in people table.
SELECT *
FROM (values row('Shane'),
row('Ricky'),
row('Mark')) t1 (Name)
WHERE NOT EXISTS (SELECT 1 FROM people P where P.Name = T1.Name)
or perhaps: (I don't think you need to specify a table in mySQL if I recall.)
SELECT *
FROM (SELECT 'Shane' as Name UNION ALL
SELECT 'Ricky' UNION ALL
SELECT 'Mark') t1
WHERE NOT EXISTS (SELECT 1 FROM people P where P.Name = T1.Name)
So the above is the SQL for your sql =
statement
Though in both cases we should specify data type for Name be it varchar, nvarchar and length...
Upvotes: 0
Reputation: 2027
You can use the SQL IN
operator, selecting the values already in the table;
SELECT * FROM people WHERE name IN (...your values...)
and then finding the difference between the two lists:
not_in_db = list(set(names).difference(set(results)))
Upvotes: 1