mysql ...in where clause is ambiguous

The error you get tells you that the column CategoryID in your WHERE clause is ambiguous, that means that the system has a problem to identify the appropriate column because there are multiple CategoryID columns.

In order to fix this problem, use the alias to specify which column you want to use for your WHERE clause:

SELECT cat2.CategoryID AS CategoryID
    ,cat2.Name AS CategoryName
    ,COUNT(p.ProductID) AS CountProducts
FROM Category AS cat
INNER JOIN Category AS cat2 ON cat2.ParrentCategoryID = cat.CategoryID
INNER JOIN Products AS p ON p.CategoryID = cat2.CategoryID
WHERE cat.CategoryID = '876'
GROUP BY cat2.CategoryID, cat2.Name
ORDER BY cat2.Name

I also changed a bit the query to get the same result but instead of using a combination of LEFT JOIN + IN clause + sub query, i used INNER JOIN clauses. With this query you only need to define your desired CategoryID once and it will automatically get every child categories.

I'm not sure that your query runs correctly because you're using the COUNT function without grouping the results by CategoryID...

Hope this will help you.


The "ambiguous column" error means that there's a reference to a column identifier, and MySQL has two (or more) possible columns that match the specification.

In this specific case, it's the reference to CategoryID column in the WHERE clause.

It's "ambiguous" whether CategoryID is meant to refer to the CategoryID column from cat, or refer to the CategoryID column from p.

The fix is to qualify the column reference with the table alias to remove the ambiguity. That is, in place of CategoryID, specify either cat.CategoryID or p.CategoryID.


Some additional notes:

It's very odd to have an IN (subquery) predicate in the ON clause. If CategoryID is not guaranteed to be unique in the Category table, this query would likely generate more rows than would be expected.

The normal pattern for a query like this would be something akin to:

SELECT cat.CategoryID     AS CategoryID
     , COUNT(p.ProductID) AS CountProducts
  FROM Category cat
  LEFT 
  JOIN Products p
    ON p.CategoryID = cat.CategoryID 
 WHERE cat.ParrentCategoryID = '876'
 ORDER BY cat.Name

Normally, the join predicates in the ON clause reference columns in two (or more) tables in the FROM clause. (That's not a SQL requirement. That's just the usual pattern.)

The predicate in the ON clause of the query above specifies that the value of the CategoryID column from the cat (Category) table match the value in the CategoryID column from the p (Product) table.

Also, best practice is to qualify all columns referenced in a query with the name of the table, or a table alias, even if the column names are not ambiguous. For example, the Name column in the ORDER BY clause.

One big benefit of this is that if (at some time in the future) a column named Name is added to the Products table, the query with an unqualified reference to Name would (then) begin to throw an "ambiguous column" error for the that reference. So, qualifying all column names avoids a working query "breaking" when new columns are added to existing tables.

Another big benefit is that to the reader of the statement. MySQL can very quickly look in the dictionary, to find which table Name is in. But readers of the SQL statement (like myself) who do not "know" which table contains the column named Name, would also need to look at the table definitions to find out. If the name were qualified, we would already "know" which table that column was from.

Tags:

Mysql

Sql