- How do I find rows in one table with no match in another in SQL?
- Ask in plain English — 'customers who have never placed an order.' nlqdb compiles an anti-join: `LEFT JOIN orders ON ... WHERE orders.id IS NULL` keeps the customers that found no matching order, or the equivalent `NOT EXISTS (SELECT 1 FROM orders WHERE ...)`. It runs the query and shows the SQL, so you can confirm it used a NULL-safe shape rather than `NOT IN`.
- Why does NOT IN return no rows in SQL?
- Because of a NULL in the subquery. `id NOT IN (SELECT customer_id FROM orders)` is true only when `id` differs from every returned value — but if one `customer_id` is NULL, the comparison is 'unknown', so the predicate is never true and you get zero rows. Use `NOT EXISTS` or a `LEFT JOIN ... IS NULL` instead; nlqdb compiles the NULL-safe form and shows it in the SQL.
- What's the difference between LEFT JOIN IS NULL and NOT EXISTS?
- For a plain anti-join they return the same rows. `NOT EXISTS` is a correlated subquery that stops at the first match and is NULL-safe by construction. `LEFT JOIN ... WHERE b.key IS NULL` keeps every left row that found no partner — but if the join key isn't unique it can multiply rows before the filter. nlqdb picks one from your phrasing and shows the clause in the SQL.
- Can I run an anti-join on a Postgres database I already run?
- Yes — connect it with the signed-in BYO connect verb (`nlq db connect`, `SK-DBCONN-001`; see /solve/query-existing-postgres-in-natural-language) and ask 'rows with no match' in place, no ETL into a separate store. The honest limits: BYO connect is signed-in only (not the public embed), and nlqdb returns the unmatched rows read-only — it doesn't persist the result set for you.