How to Fix MySQL Error 1248: Every Derived Table Must Have Its Own Alias

ERROR 1248 (42000): Every derived table must have its own alias is raised when a subquery used as a table in the FROM clause (a derived table) is not given an alias. The error symbol is ER_DERIVED_MUST_HAVE_ALIAS.

Impact

This is a syntax error caught at parse time — MySQL rejects the query before executing it. No rows are read or written, and no transaction is started. The error is immediate and deterministic: the same query will always fail until the alias is added.

Developers most commonly encounter this when writing complex reporting queries, refactoring a flat query into a subquery, or generating queries programmatically. ORMs that construct raw subquery expressions (Hibernate native queries, SQLAlchemy text(), ActiveRecord from with a literal string) will surface this as a database-level exception rather than an ORM-level validation error.

Common Causes

  1. Subquery in FROM without an alias. A subquery placed directly in the FROM clause has no AS alias_name clause appended.

  2. Joining a subquery without an alias. The same rule applies when a subquery is used in a JOIN expression — each subquery-derived relation must have an alias.

  3. CTEs confused with derived tables. Developers new to MySQL sometimes write a subquery where they intended a CTE (WITH clause), forgetting that inline subqueries still need aliases even when a CTE would not require the alias on its own reference.

  4. Programmatically generated SQL. Query builders or templating code that assembles subquery fragments may omit the alias, especially when refactoring a literal table name to a subquery.

  5. Nested subqueries missing an alias at any level. Each subquery at every nesting level that appears in a FROM or JOIN position requires its own alias — not just the outermost one.

Troubleshooting and Resolution Steps

  1. Identify the unaliased subquery. MySQL's error message does not point to a line number, so scan your FROM and JOIN clauses for any (SELECT ...) that lacks an AS <name> suffix.

    Failing query:

    SELECT dept, total
    FROM (
      SELECT department AS dept, SUM(salary) AS total
      FROM employees
      GROUP BY department
    );
    

    Fix — add an alias after the closing parenthesis:

    SELECT dept, total
    FROM (
      SELECT department AS dept, SUM(salary) AS total
      FROM employees
      GROUP BY department
    ) AS dept_totals;
    
  2. Fix subqueries used in JOIN clauses. The alias requirement applies equally to joined subqueries.

    Failing query:

    SELECT e.name, s.total
    FROM employees e
    JOIN (
      SELECT employee_id, SUM(amount) AS total
      FROM sales
      GROUP BY employee_id
    ) ON e.id = employee_id;
    

    Fix:

    SELECT e.name, s.total
    FROM employees e
    JOIN (
      SELECT employee_id, SUM(amount) AS total
      FROM sales
      GROUP BY employee_id
    ) AS s ON e.id = s.employee_id;
    
  3. Rewrite as a CTE for readability. If the subquery is complex, a Common Table Expression (available since MySQL 8.0) can make the intent clearer and avoids the inline alias entirely at the use site:

    WITH dept_totals AS (
      SELECT department AS dept, SUM(salary) AS total
      FROM employees
      GROUP BY department
    )
    SELECT dept, total
    FROM dept_totals;
    
  4. Check nested subqueries at every level. When subqueries are nested, each level that appears in a FROM or JOIN position needs an alias:

    -- Both the inner and outer derived tables need aliases
    SELECT outer_q.dept, outer_q.avg_total
    FROM (
      SELECT dept, AVG(total) AS avg_total
      FROM (
        SELECT department AS dept, SUM(salary) AS total
        FROM employees
        GROUP BY department
      ) AS inner_agg
      GROUP BY dept
    ) AS outer_q;
    
  5. Audit query-building code. If the query is generated dynamically, search for places where a subquery string is concatenated into a FROM or JOIN clause without appending an alias. A simple check is to ensure every ) that closes a subquery in those positions is followed by AS.

Additional Information

  • The SQLSTATE code is 42000 (Syntax Error or Access Rule Violation), which places this firmly in the parse/syntax error category — not a runtime or permission issue.
  • This rule applies to all MySQL versions, including MySQL 5.5, 5.6, 5.7, and 8.x. There is no strict mode flag that affects it.
  • MariaDB enforces the same rule and raises the same error code and message.
  • PostgreSQL, by contrast, issues error 42601 with the message "subquery in FROM must have an alias" — the semantic requirement is the same, but the error code differs.
  • Aliases do not need to be unique across the entire query, but they must be unique within the same query scope to avoid ambiguous references.
  • The AS keyword is optional syntactically — FROM (SELECT ...) t without AS is valid — but using AS improves readability.

Frequently Asked Questions

Why does MySQL require an alias for derived tables at all? MySQL needs to give the result set of a subquery a name so that outer parts of the query can reference its columns unambiguously. Without an alias, the optimizer and parser have no way to qualify column references back to that relation.

Does this apply to subqueries in WHERE or SELECT, or only FROM? Only subqueries that appear in the FROM or JOIN clause (derived tables) require an alias. Scalar subqueries in SELECT or WHERE (e.g., WHERE id IN (SELECT id FROM ...)) do not.

I added an alias but still get an error — what else could be wrong? Check that the alias is placed immediately after the closing ) of the subquery, before any ON, WHERE, or GROUP BY clause. Also verify there are no nested subqueries at inner levels that are also missing aliases.

Can I use the same alias name for two subqueries in the same query? Not in the same scope. If two subqueries appear at the same nesting level in a FROM clause, they must have distinct aliases. You can reuse a name at different nesting levels, but it is best avoided for clarity.

Subscribe to the Pulse Newsletter

Get early access to new Pulse features, insightful blogs & exclusive events , webinars, and workshops.

We use cookies to provide an optimized user experience and understand our traffic. To learn more, read our use of cookies; otherwise, please choose 'Accept Cookies' to continue using our website.