【问题标题】:MySQL Query Problem with Alias and Aggregate Functions别名和聚合函数的 MySQL 查询问题
【发布时间】:2011-04-08 01:55:14
【问题描述】:

我有一个麻烦的 MySQL 查询如下:

SELECT camera_id, ((avg(low_price) + avg(high_price)) / 2) as avg_price
FROM camera_general, camera_products
WHERE camera_id = ir_camera_id
AND dp_post_dt IS NOT NULL
AND dp_post_dt NOT LIKE '0000%'
AND currently_manufactured = 'Yes'
AND ((no_of_sellers >= 0) OR ((TO_DAYS(CURRENT_DATE) - TO_DAYS(dp_post_dt)) < 120))
AND avg_price < 150 
AND camera_id != 1411
AND camera_id != 9
ORDER BY rand();

这个产生了“'where 子句'中的“未知列'avg_price'”错误。我理解这是因为 WHERE 子句中不允许使用列别名。 (如果我在此过程中有任何错误,请纠正我。)

所以,我像这样调整了查询​​:

SELECT camera_id, ((avg(low_price) + avg(high_price)) / 2) as avg_price
FROM camera_general, camera_products
WHERE camera_id = ir_camera_id
AND dp_post_dt IS NOT NULL
AND dp_post_dt NOT LIKE '0000%'
AND currently_manufactured = 'Yes'
AND ((no_of_sellers >= 0) OR ((TO_DAYS(CURRENT_DATE) - TO_DAYS(dp_post_dt)) < 120))
AND ((avg(low_price) + avg(high_price)) / 2) < 150 
AND camera_id != 1411
AND camera_id != 9
ORDER BY rand();

用实际计算替换别名,此查询产生错误:“无效使用组函数”。我理解这是因为 avg() 直到 WHERE 子句完成处理后才会发生。

然后我尝试了:

SELECT camera_id, ((avg(low_price) + avg(high_price)) / 2) as avg_price
FROM camera_general, camera_products
ORDER BY rand();
HAVING camera_id = ir_camera_id
AND dp_post_dt IS NOT NULL
AND dp_post_dt NOT LIKE '0000%'
AND currently_manufactured = 'Yes'
AND ((no_of_sellers >= 0) OR ((TO_DAYS(CURRENT_DATE) - TO_DAYS(dp_post_dt)) < 120))
AND avg_price < 150 
AND camera_id != 1411
AND camera_id != 9;

将 WHERE 替换为 HAVING 并产生此错误“您的 SQL 语法有错误;请查看与您的 MySQL 服务器版本相对应的手册,以获取在 'HAVING camera_id = ir_camera_id' 附近使用的正确语法”。

在这一点上,我觉得我在黑暗中射击,试图让这个查询工作。有人会指导我正确的方向以使这个查询正常运行吗?

谢谢!

【问题讨论】:

    标签: mysql aggregate-functions mysql-error-1111


    【解决方案1】:
    1. 虽然您可以使用WHERE 指定连接条件,但最好在LEFT[INNER] JOIN 子句中执行。
    2. 如果要按非聚合字段过滤,请将过滤器放入WHERE,如果需要按聚合过滤,请将条件移入HAVING
    3. 在同一查询中使用聚合和非聚合时,不要忘记GROUP BY

      SELECT camera_id, ((avg(low_price) + avg(high_price)) / 2) as avg_price FROM camera_general
      INNER JOIN camera_products ON (camera_id = ir_camera_id)
      WHERE dp_post_dt IS NOT NULL
      AND dp_post_dt NOT LIKE '0000%'
      AND currently_manufactured = 'Yes'
      AND ((no_of_sellers >= 0) OR ((TO_DAYS(CURRENT_DATE) - TO_DAYS(dp_post_dt)) < 120))
      AND camera_id != 1411 AND camera_id != 9
      GROUP BY camera_id
      HAVING avg_price < 150
      ORDER BY rand();

    【讨论】:

    • 谢谢 - 这工作。我理解(向上看)#2 和#3。但是,我仍然有点模糊,为什么做一个 LEFT[INNER] JOIN 更好?
    • WHERE 中的连接条件是旧语法 (ANSI SQL 1989)。它只支持交叉和内连接(对于外连接,不同的服务器有不同的扩展,例如 TSQL 有*= AND =*)。 JOIN 关键字在 SQL 1992 中引入并支持外连接。使用JOIN 可以使您的查询清晰,并且在指定连接条件时使用它被认为是一种很好的样式。
    • 谢谢。感谢您的解释和帮助!
    【解决方案2】:

    ORDER 子句应该在 HAVING 子句之后。 (除了你在ORDER BY rand() 后面加上一个分号; 然后继续HAVING,这实际上是另一个查询的开始,因为第一个以; 结束)。

    【讨论】:

    • 谢谢。分号是重新排列之前所有内容的混合。但是,在 HAVING 之后移动 ORDER 子句确实可以解决一个问题,但迫使我将 HAVING 子句中使用的所有非聚合列添加到 GROUP BY 子句中。
    猜你喜欢
    • 1970-01-01
    • 2020-05-15
    • 2011-07-26
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    • 2017-06-04
    相关资源
    最近更新 更多