SQL SELECT From Multiple Tables Without JOIN: 4 Ways

AAI for Database TeamSEP 22 2026

You can run a SQL SELECT from multiple tables without JOIN in four useful ways: UNION or UNION ALL to stack compatible rows, scalar subqueries to return independent values, EXISTS or IN to filter one table from another, and a Cartesian product when you genuinely need every possible combination. The right method depends on the shape of the result, not on avoiding the JOIN keyword.

If you need columns from related rows on the same line, an explicit JOIN is usually the clearest and safest answer. Hiding the relationship in older comma syntax does not remove the join. It only makes accidental row multiplication easier to miss.

Quick decision table

  • Use UNION ALL when tables contain the same kind of rows and you want to stack them.
  • Use UNION when you want to stack rows and remove duplicates.
  • Use scalar subqueries when each table contributes one independent value, such as a count or total.
  • Use EXISTS or IN when one table filters rows from another but you do not need columns from both.
  • Use CROSS JOIN only when every combination is intentional, such as every plan paired with every region.
  • That is the entire decision in practical terms. Start by asking whether you want more rows, more columns, a filter, or every combination. Then choose the SQL construct that directly expresses that result.

    Method 1: Stack rows with UNION or UNION ALL

    UNION combines the result of one SELECT with another. Each SELECT must return the same number of columns, and corresponding columns need compatible data types. Column names in the final result normally come from the first SELECT.

    SELECT customer_id, created_at, 'web' AS source FROM web_signups UNION ALL SELECT customer_id, created_at, 'partner' AS source FROM partner_signups;

    This produces one list of signups from two tables. UNION ALL keeps every row and is normally faster because the database does not have to remove duplicates. Use plain UNION only when duplicate removal is a real business requirement.

    UNION is not a replacement for JOIN. It adds rows vertically. A JOIN adds related columns horizontally. If one table contains customers and another contains their subscriptions, UNION cannot sensibly place a customer name beside a subscription plan.

    Method 2: Return independent values with scalar subqueries

    A scalar subquery returns exactly one value. It is useful for a compact KPI summary where each metric comes from a different table and the metrics do not need row-by-row matching.

    SELECT (SELECT COUNT(*) FROM users WHERE created_at >= CURRENT_DATE) AS new_users_today, (SELECT COUNT(*) FROM orders WHERE status = 'paid') AS paid_orders, (SELECT COUNT(*) FROM tickets WHERE status = 'open') AS open_tickets;

    The query returns one row with three columns. This is often cleaner than forcing unrelated tables into a join and then fighting inflated counts caused by repeated combinations.

    Each scalar subquery must return one row and one column. Aggregates such as COUNT, SUM, MIN, and MAX naturally satisfy that requirement. A subquery that returns several rows will cause an error in most databases.

    Performance still matters. Three selective subqueries against indexed columns may be cheap; dozens of full-table scans may not be. Check the execution plan on large production tables and use a reporting replica when analytical load could affect customer traffic.

    Method 3: Filter with EXISTS or IN

    Sometimes you want rows from one table only, but the eligibility rule lives in another table. EXISTS expresses that intent without returning columns from the second table.

    SELECT u.id, u.email FROM users AS u WHERE EXISTS ( SELECT 1 FROM subscriptions AS s WHERE s.user_id = u.id AND s.status = 'active' );

    This returns users who have at least one active subscription. The result contains user columns only. Although the SQL contains no JOIN keyword, the correlated condition still relates the two tables through user_id.

    IN can express a similar filter when the subquery returns one column.

    SELECT id, email FROM users WHERE id IN ( SELECT user_id FROM subscriptions WHERE status = 'active' );

    Modern query optimizers can often produce similar plans for EXISTS and IN, but their null behavior is not identical in every form. Be especially careful with NOT IN: if its subquery contains NULL, the comparison can become unknown and return no rows. NOT EXISTS is generally easier to reason about for exclusion checks.

    Method 4: Create combinations with CROSS JOIN

    A CROSS JOIN returns every row from the first table paired with every row from the second. Ten plans and five regions produce 50 combinations. This is correct for generating a complete matrix, testing all rule combinations, or building a calendar scaffold.

    SELECT p.plan_name, r.region_name FROM plans AS p CROSS JOIN regions AS r;

    Older SQL allows the same operation with comma-separated tables.

    SELECT p.plan_name, r.region_name FROM plans AS p, regions AS r;

    Prefer the explicit CROSS JOIN. It tells the next reader that the Cartesian product is intentional. A comma followed by a forgotten WHERE condition looks almost identical but can multiply a large table into millions or billions of rows.

    Why comma-separated tables are still a join

    You may see queries that list several tables in FROM and connect them in WHERE.

    SELECT u.email, o.total FROM users AS u, orders AS o WHERE u.id = o.user_id;

    This is an implicit inner join. It is valid in many SQL engines, but it is not meaningfully a query without a join. The relationship has merely moved from an ON clause to the WHERE clause.

    Use explicit JOIN syntax for related rows. It separates relationship conditions from filters, makes outer joins possible to read correctly, and reduces the chance that a missing predicate creates a Cartesian product.

    SELECT u.email, o.total FROM users AS u INNER JOIN orders AS o ON o.user_id = u.id;

    Common mistakes to avoid

    Mistake 1: Using UNION for tables with different meanings

    Do not stack customers and invoices merely because both have an id column. Compatible data types do not make the rows semantically compatible. Add a source column when combining true peer datasets so downstream users can see where each row came from.

    Mistake 2: Removing duplicates without a reason

    UNION performs duplicate elimination; UNION ALL does not. If duplicates are valid or impossible, UNION adds unnecessary work and can hide a data-quality problem. Choose deliberately.

    Mistake 3: Counting after multiplying rows

    Joining users, orders, and support tickets in one query can multiply orders by tickets for each user. Counts and sums then look plausible but are wrong. Aggregate each fact table first, use scalar subqueries for independent totals, or join pre-aggregated results.

    Mistake 4: Treating no JOIN keyword as a performance goal

    Databases optimize logical operations, not stylistic tricks. EXISTS may become a semi-join internally, and comma syntax may become an inner join. Optimize for correct result shape, useful indexes, limited scans, and a readable execution plan.

    How to choose the correct pattern step by step

  • Write down what one output row represents: a user, an order, a daily total, or a combination.
  • If the tables hold the same entity and columns, stack rows with UNION ALL.
  • If the result is one summary row, use scalar aggregate subqueries.
  • If the second table only decides eligibility, use EXISTS or IN.
  • If you need columns from matching related rows, use an explicit JOIN.
  • If you need every possible pair, use CROSS JOIN and estimate the row count first.
  • Test the query on a small known dataset. Check the expected row count, inspect duplicates, and verify at least one boundary case such as a user with no subscription or a table containing NULL values. Correct-looking SQL can still answer the wrong business question.

    Can I query multiple tables without knowing which SQL method to use?

    Yes. A natural-language database tool can translate the result you describe into SQL, but you should still verify the first answer. State the entity, metric, filters, and time window clearly: for example, 'Show each active customer with total paid revenue in the last 90 days, including customers with zero orders.' That request signals a left join and aggregation even if you never name either concept.

    With AI for Database, you can ask a connected database in plain English, inspect the generated result, save a useful answer as a self-refreshing dashboard, and trigger email, Slack, or webhook actions when a threshold changes. It supports PostgreSQL, MySQL, SQLite, MongoDB, Supabase, SQL Server, BigQuery, and other sources.

    The practical rule is simple: use SQL directly when you need exact control and can review the query. Use a natural-language layer when non-technical teammates need safe self-service answers. In either case, connect with read-only credentials, limit accessible schemas, and validate important numbers against a trusted report.

    The bottom line

    SQL can select from multiple tables without the JOIN keyword, but each alternative solves a different problem. UNION stacks rows, scalar subqueries place independent values in one result, EXISTS and IN filter by another table, and CROSS JOIN creates every combination.

    When you need related columns on the same row, use an explicit JOIN. When your team wants the answer without choosing SQL syntax, try AI for Database free with a read-only connection and verify the first result against a known number.

    Frequently asked questions

    Can SQL select from two tables without a JOIN?

    Yes. Use UNION or UNION ALL to stack compatible rows, scalar subqueries for independent values, EXISTS or IN to filter from another table, or CROSS JOIN for every possible combination.

    What happens if I list two tables in FROM without a condition?

    The database returns a Cartesian product: every row in the first table paired with every row in the second. The result contains the product of both row counts.

    Is comma syntax the same as JOIN?

    Comma-separated tables plus a relationship condition in WHERE are an implicit inner join. Explicit JOIN syntax is clearer because it separates table relationships from ordinary filters.

    Should I use UNION or JOIN for multiple tables?

    Use UNION to add similar rows beneath each other. Use JOIN to place related columns beside each other. UNION requires compatible column counts and types; JOIN requires a relationship between rows.

    How can a non-technical user query several tables?

    A natural-language query tool can generate the SQL from a precise business question. Use read-only access and verify the first result, especially when joins, duplicate rows, or business definitions affect the metric.

    Ready to try AI for Database?

    Query your database in plain English. No SQL required. Start free today.