Error 352: AMBIGUOUS_COLUMN_NAME
Tip
This error occurs when a column reference in a query is ambiguous because it could refer to columns from multiple tables.
It indicates that ClickHouse cannot determine which table's column you're referencing, typically in JOIN queries or when using duplicate column names.
Most common causes
-
Column exists in multiple joined tables
- The same column name appears in two or more tables being joined
- No table qualifier used to specify which table's column is needed
- Ambiguous column reference in
SELECT, WHERE, GROUP BY, or ORDER BY clauses
-
Self-join without proper aliases
- Joining a table to itself
- Column referenced without table alias qualifier
- Both instances of the table have the same column
-
Analyzer behavior with joined tables
- New analyzer (enabled with
allow_experimental_analyzer = 1) enforces stricter rules
- Old analyzer preferred left table in ambiguous cases (non-standard SQL)
- Table aliases don't block original table name identifiers
-
Multiple JOIN operations
- Column present in multiple tables across chain of JOINs
- Missing table qualifiers on shared column names
- Complex queries with many joined tables
-
Column name conflicts in subqueries
- Subquery aliases creating duplicate column names
- Derived tables with overlapping column names
UNION queries with inconsistent column naming
Common solutions
1. Use explicit table qualifiers
-- WRONG: Ambiguous column reference
SELECT id, name
FROM table1
JOIN table2 ON table1.user_id = table2.user_id;
-- CORRECT: Qualify columns with table names
SELECT
table1.id,
table1.name,
table2.name AS name2
FROM table1
JOIN table2 ON table1.user_id = table2.user_id;
2. Use table aliases for clarity
-- WRONG: Ambiguous in self-join
SELECT t4.c0
FROM t4
INNER JOIN t4 AS right_0 ON t4.c0 = right_0.c0;
-- CORRECT: Use aliases consistently
SELECT
left_t.c0 AS left_c0,
right_t.c0 AS right_c0
FROM t4 AS left_t
INNER JOIN t4 AS right_t ON left_t.c0 = right_t.c0;
3. Alias duplicate column names
-- WRONG: Both tables have 'name' column
SELECT *
FROM users u
JOIN profiles p ON u.id = p.user_id;
-- CORRECT: Alias one or both
SELECT
u.id,
u.name AS user_name,
p.name AS profile_name
FROM users u
JOIN profiles p ON u.id = p.user_id;
4. Use USING clause for common columns
-- Instead of ON clause
SELECT *
FROM table1
JOIN table2 USING (user_id, date);
-- This automatically qualifies columns and avoids ambiguity
5. Enable the new analyzer (if needed)
-- New analyzer provides better error messages and handling
SET allow_experimental_analyzer = 1;
-- Query will now give clearer error about ambiguity
SELECT * FROM t1 JOIN t2 ON t1.id = t2.id WHERE name = 'test';
6. Specify columns explicitly instead of SELECT *
-- WRONG: SELECT * can create ambiguity
SELECT *
FROM orders o
JOIN customers c ON o.customer_id = c.id;
-- CORRECT: List needed columns explicitly
SELECT
o.order_id,
o.order_date,
c.id AS customer_id,
c.customer_name
FROM orders o
JOIN customers c ON o.customer_id = c.id;
Common scenarios
Scenario 1: Simple JOIN with shared column name
Error: JOIN database.t4 ALL INNER JOIN database.t4 AS right_0 ON t4.c0 = right_0.c0
ambiguous identifier 't4.c0'
Cause: Column c0 exists in both sides of self-join.
Solution:
-- Use proper table aliases
SELECT
left_t.c0 AS left_value,
right_t.c0 AS right_value
FROM t4 AS left_t
INNER JOIN t4 AS right_t ON left_t.id = right_t.id;
Scenario 2: Multi-table JOIN ambiguity
Error: Ambiguous column 'id' in SELECT
Cause: Column id appears in multiple joined tables.
Solution:
-- Qualify all columns
SELECT
t1.id AS t1_id,
t2.id AS t2_id,
t3.id AS t3_id
FROM t1
JOIN t2 ON t1.key = t2.key
JOIN t3 ON t2.key = t3.key;
Scenario 3: WHERE clause ambiguity
Error: Ambiguous column reference in WHERE clause
Cause: Column used in WHERE exists in multiple tables.
Solution:
-- WRONG
SELECT * FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE status = 'active';
-- CORRECT: Specify which table's status
SELECT * FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE o.status = 'active';
Scenario 4: Analyzer differences
Query works with old analyzer but fails with new analyzer
Cause: New analyzer enforces SQL standard more strictly.
Solution:
-- Option 1: Fix query to be explicit
SELECT t1.col FROM t1 JOIN t2 ON t1.id = t2.id;
-- Option 2: Temporarily disable new analyzer
SET allow_experimental_analyzer = 0;
Scenario 5: Column name from wrong table in multi-JOIN
Query accidentally uses t1.d but d doesn't exist in t1
(exists in t2 but query succeeds incorrectly)
Cause: Bug in old query analyzer with multi-table JOINs.
Solution:
- Enable new analyzer:
SET allow_experimental_analyzer = 1
- Or explicitly qualify all column references
- Update to version with new analyzer as default
Debugging steps
-
Identify the ambiguous column:
-
Error message shows: "ambiguous identifier 't4.c0'"
The column name causing ambiguity is listed in the error.
-
Check which tables have this column:
-- Find column across tables
SELECT
database,
table,
name AS column_name,
type
FROM system.columns
WHERE name = 'c0' -- Replace with your column
AND database = 'your_database';
-
Review query structure:
- Identify all tables in the query
- Check which tables have the ambiguous column
- Note where column is referenced without qualifier
-
Use EXPLAIN to understand the query:
EXPLAIN SYNTAX
SELECT * FROM t1 JOIN t2 ON t1.id = t2.id;
-
Test with the new analyzer:
-- Enable new analyzer for better error messages
SET allow_experimental_analyzer = 1;
SELECT your_query;
Special considerations
Old vs. new analyzer behavior:
- Old analyzer: Preferred left table in ambiguous cases (non-SQL standard)
- New analyzer: Strictly enforces disambiguation (SQL standard compliant)
- Migration: Queries working on old analyzer may need fixes for new analyzer
Self-joins:
- Always use aliases for both table references
- Qualify every column reference
- Use descriptive aliases (not just
t1, t2)
Multiple JOINs:
- Risk of ambiguity increases with each JOIN
- Some column names may work in 2-table JOIN but fail in 3+ table JOIN
- Old analyzer had bugs allowing incorrect column references from wrong tables
Table aliases don't block original names:
-- Even with alias, original table name still works
SELECT t1.col -- Works
FROM table1 AS t1;
-- This can cause ambiguity in joins
SELECT table1.col -- Also works, but can be ambiguous
FROM table1 AS t1
JOIN table2 AS t2 ON...;
Common patterns to avoid
-- AVOID: Unqualified columns in JOIN
SELECT id, name, email
FROM users
JOIN profiles ON users.id = profiles.user_id;
-- AVOID: Ambiguous WHERE conditions
SELECT *
FROM orders
JOIN customers ON orders.customer_id = customers.id
WHERE status = 'active'; -- Which table's status?
-- AVOID: GROUP BY without qualifiers
SELECT region, COUNT(*)
FROM sales
JOIN stores ON sales.store_id = stores.id
GROUP BY region; -- Which table's region?
-- AVOID: Self-join without clear aliases
SELECT * FROM t JOIN t ON t.id = t.parent_id;
Best practices
-- GOOD: Fully qualified columns
SELECT
o.id AS order_id,
o.status AS order_status,
c.id AS customer_id,
c.status AS customer_status
FROM orders AS o
JOIN customers AS c ON o.customer_id = c.id
WHERE o.status = 'active'
AND c.status = 'verified'
GROUP BY o.region, c.region
ORDER BY o.created_at DESC;
-- GOOD: Use USING for common columns
SELECT *
FROM orders
JOIN order_items USING (order_id);
-- GOOD: Clear aliases in self-joins
SELECT
parent.id AS parent_id,
child.id AS child_id,
parent.name AS parent_name,
child.name AS child_name
FROM categories AS parent
JOIN categories AS child ON child.parent_id = parent.id;
Analyzer-specific information
The new query analyzer (experimental in older versions, default in newer versions) handles ambiguity differently:
-- Check if analyzer is enabled
SELECT getSetting('allow_experimental_analyzer');
-- Enable for stricter checking
SET allow_experimental_analyzer = 1;
-- Disable to use old behavior (temporary workaround)
SET allow_experimental_analyzer = 0;
Note
The new analyzer will become the default.
It's recommended to fix queries to work with it rather than relying on old behavior.
UNKNOWN_IDENTIFIER (47): Column doesn't exist at all
AMBIGUOUS_COLUMN_NAME (352): Column exists in multiple tables
AMBIGUOUS_IDENTIFIER (207): General ambiguous identifier (older error code)
BAD_ARGUMENTS (36): Wrong arguments, sometimes related to column issues
Migration to new analyzer
If enabling the new analyzer causes AMBIGUOUS_COLUMN_NAME errors in previously working queries:
-
Add table qualifiers:
-- Change unqualified columns
SELECT id, name -- May fail with new analyzer
-- To qualified columns
SELECT t1.id, t1.name
-
Use explicit aliases:
-- Add aliases for duplicate names
SELECT
t1.status AS t1_status,
t2.status AS t2_status
-
Test incrementally:
-- Test one query at a time with analyzer
SET allow_experimental_analyzer = 1;
SELECT your_query;
If you're experiencing this error:
- Identify which column name is ambiguous from the error message
- Determine which tables in the query have this column
- Add table qualifiers (e.g.,
table.column or alias.column) to all references
- Use table aliases for clarity in complex JOINs
- Test with new analyzer to catch these issues proactively
- Consider using
USING clause for join columns with same name
- List columns explicitly instead of
SELECT * to avoid hidden ambiguity
Related documentation: