【问题标题】:mysql ...in where clause is ambiguousmysql ...in where 子句不明确
【发布时间】:2014-09-05 04:48:49
【问题描述】:
SELECT
                cat.CategoryID as CategoryID,
                count(p.ProductID) as CountProducts
            FROM 
                Category as cat
                LEFT JOIN Products as p on p.CategoryID IN 
                       (SELECT CategoryID FROM Category as cd 
                           WHERE cd.ParrentCategoryID = '876')
            WHERE 
                CategoryID = '876'
            ORDER by Name

我们收到错误 - “where 子句中的列 'CategoryID' 不明确”。

请告诉我如何正确?

【问题讨论】:

  • CategoryID 在两个表中。用表的名称来命名标识符列并不是一个好主意 - 只是 id 是行业标准,因为它效果最好。
  • IN (subquery) 谓词在ON 子句中的使用非常奇怪。通常,ON 子句中的谓词引用 FROM 子句中表的列。 (我很难理解所需的结果集实际上是什么。)

标签: mysql sql


【解决方案1】:

您收到的错误告诉您WHERE 子句中的CategoryID 列不明确,这意味着系统在识别适当的列时存在问题,因为有多个CategoryID 列。

为了解决这个问题,使用别名来指定你想为你的WHERE 子句使用哪一列:

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

我还稍微更改了查询以获得相同的结果,但我没有使用 LEFT JOIN + IN 子句 + 子查询的组合,而是使用了 INNER JOIN 子句。 使用此查询,您只需定义一次所需的CategoryID,它将自动获取每个子类别。

我不确定您的查询是否正确运行,因为您使用的是COUNT 函数,而没有按CategoryID 对结果进行分组...

希望这会对你有所帮助。

【讨论】:

  • +1。这是更常见的查询模式; ON 子句中的谓词引用 FROM 子句中表的列(与 OP 查询中的 IN (subquery) 相比。
  • 哦,对不起 - 漫长的夜晚,我没有看到小错误(= 抱歉 +1 寻求帮助和新知识
  • @learner 如果您从中学到了一些东西,那很高兴,小错误是开发人员生活的一部分;-) 不要忘记将其中一个答案标记为“已接受”以关闭问题
【解决方案2】:

“歧义列”错误意味着存在对列标识符的引用,并且 MySQL 有两个(或更多)可能的列与规范匹配。

在这种特定情况下,它是对WHERE 子句中的CategoryID 列的引用。

CategoryID 是指来自catCategoryID 列,还是指来自pCategoryID 列,这是“不明确的”。

解决方法是使用表别名限定列引用以消除歧义。也就是说,代替CategoryID,指定cat.CategoryIDp.CategoryID


一些补充说明:

ON 子句中有一个IN (subquery) 谓词很奇怪。如果不能保证 CategoryIDCategory 表中是唯一的,则此查询可能会生成比预期更多的行。

这样的查询的正常模式类似于:

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

通常,ON 子句中的连接谓词引用 FROM 子句中两个(或更多)表中的列。 (这不是 SQL 要求。这只是通常的模式。)

上述查询的ON 子句中的谓词指定cat(类别)表中CategoryID 列的值匹配CategoryID 列中的值来自p(产品)表。

此外,最佳做法是使用表名或表别名来限定查询中引用的所有列,即使列名没有歧义。例如,ORDER BY 子句中的Name 列。

这样做的一大好处是,如果(在将来的某个时间)将名为 Name 的列添加到 Products 表中,则带有对 Name 的非限定引用的查询将(然后)开始为该引用引发“不明确的列”错误。因此,在将新列添加到现有表时,限定所有列名可以避免工作查询“中断”。

另一个很大的好处是对声明的读者来说。 MySQL 可以非常快速地在字典中查找 Name 所在的表。但是 SQL 语句的读者(如我自己)不“知道”哪个表包含名为 Name 的列,也需要查找在表定义中找出答案。如果名称是合格的,我们就已经“知道”该列来自哪个表。

【讨论】:

  • 抱歉问题很糟糕 - 漫长的夜晚...+1 寻求帮助
  • 赞赏说明解决方案是使用 table.column 语法指定表的简单性!
【解决方案3】:

试试WHERE cat.CategoryID = '876'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    • 2010-09-25
    • 1970-01-01
    • 2010-12-07
    • 2012-07-19
    • 2014-11-16
    • 1970-01-01
    相关资源
    最近更新 更多