别名和聚合函数的 MySQL 查询问题
Posted
技术标签:
【中文标题】别名和聚合函数的 MySQL 查询问题【英文标题】:MySQL Query Problem with Alias and Aggregate Functions 【发布时间】: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' 附近使用的正确语法”。
在这一点上,我觉得我在黑暗中射击,试图让这个查询工作。有人会指导我正确的方向以使这个查询正常运行吗?
谢谢!
【问题讨论】:
【参考方案1】:-
虽然您可以使用
WHERE
指定连接条件,但最好在LEFT[INNER] JOIN
子句中执行。
如果要按非聚合字段过滤,请将过滤器放入WHERE
,如果需要按聚合过滤,请将条件移入HAVING
在同一查询中使用聚合和非聚合时,不要忘记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 子句中。以上是关于别名和聚合函数的 MySQL 查询问题的主要内容,如果未能解决你的问题,请参考以下文章
MySQL 基础 SQL -- DQL 数据查询语言(基础查询(字段别名) where条件查询(比较运算符逻辑运算符) 聚合函数分组查询 排序查询分页查询DQL语句执行顺序)
3.1.3MySQL__数据库基本建表查询,登录,sql语句,建表语句,修改表结构,增删改查,as别名,limit分页,distinct去重,聚合函数,
MySQL 基础 -- SQL(通用语法SQL分类DDL 数据定义语言(含数据类型说明)DML 数据操作语言DQL 数据查询语言(别名去重聚合函数排序分页)DCL 数据控制语言)