selecting rows with id from another table
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
Selecting rows whose IDs appear in another table is one of the most common SQL tasks. The exact query shape depends on what you want back: only matching rows, rows plus related columns, or rows that merely satisfy an existence condition. In practice, the main tools are JOIN, IN, and EXISTS.
A Simple Example Schema
Assume you have two tables:
If you want orders whose customer_id matches an ID in customers, you are asking for rows linked by a foreign-key-style relationship.
Use JOIN When You Need Data From Both Tables
JOIN is usually the clearest choice when you also want columns from the related table.
This returns only orders that have a matching customer. It is a natural fit when the relationship itself matters and you want data from both sides.
You can add filters on either table:
That is easier to read than a nested subquery when the relationship is central to the query.
Use IN When You Only Need Membership
If you only need rows from one table and do not care about the other table's columns, IN can be concise.
This reads as, "Give me orders whose customer_id is one of the IDs returned by the subquery."
IN is often perfectly fine, especially when the subquery is simple and the intent is clearly membership-based.
Use EXISTS for Correlated Existence Checks
EXISTS is useful when you care about whether a related row exists, not about joining all of its columns.
This is semantically close to the IN example, but EXISTS often expresses the intention more directly for correlated checks.
It becomes especially useful when the subquery has additional conditions:
Choosing Between Them
Use JOIN when:
- you need columns from both tables
- the relationship is central to the query result
- you want readable relational structure
Use IN when:
- you only need rows from one table
- the related table is just a source of IDs
- the membership logic is simple
Use EXISTS when:
- you want to check whether a related row exists
- the condition is naturally correlated
- you want to avoid thinking of the other table as a list of values
Modern query planners can optimize many of these forms similarly, so clarity of intent is often a better first decision criterion than folklore about one always being faster.
Indexes Still Matter
Whichever syntax you choose, indexes on the relevant ID columns matter for performance.
Typical helpful indexes are:
If customers.id is the primary key, it is already indexed in most systems. Without proper indexing, even a logically correct query can become slow on large tables.
One Important Duplicate Detail
JOIN can duplicate rows if the relationship is one-to-many on the joined side. IN and EXISTS do not duplicate the outer rows in the same way. If duplicates appear unexpectedly after a JOIN, inspect the cardinality of the relationship rather than assuming SQL is behaving strangely.
Common Pitfalls
The most common mistake is using a JOIN when you only needed an existence check, then being surprised by duplicated rows from a one-to-many relationship.
Another mistake is writing an IN subquery and later needing related columns from the second table. At that point, a JOIN is usually clearer.
Developers also often forget indexes on foreign-key-style columns, which can make simple relationship queries slow on larger datasets.
Finally, avoid SELECT * in joined queries unless you truly need every column. Being explicit makes the result easier to understand and maintain.
Summary
- Use
JOINwhen you need related columns from another table. - Use
INwhen you only need to filter by a set of IDs. - Use
EXISTSwhen the real question is whether a related row exists. - Index the ID columns involved in the relationship.
- Watch for duplicate rows when joining across one-to-many relationships.
Related reading
- selecting unique values from a column
- Selection of database
- Send settings to clickhouse via http protocol using requests
- Sequel Pro and MySQL connection failed
- Serializing Sqlite3 in Python
- Set database timeout in Entity Framework
- Set NOW as Default Value for datetime datatype?
- Set user variable from result of query

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.