SQL聚合函数
好的,我这里有一个代码:SQL聚合函数,sql,oracle,function,aggregation,Sql,Oracle,Function,Aggregation,好的,我这里有一个代码: SELECT MOVIETITLE AS "Movie Title", MIN(AVG(RATING)) AS "Lowest Average Rating" FROM MOVIE, RATING WHERE MOVIE.MOVIEID = RATING.MOVIEID GROUP BY MOVIETITLE; 我需要从我的评级表中确定最低的平均评级,所以我使用了聚合函数 MIN(平均(评级)) 但我一直遇到这个错误,我不知道如何解决它: ORA-00937:没有单一
SELECT MOVIETITLE AS "Movie Title", MIN(AVG(RATING)) AS "Lowest Average Rating"
FROM MOVIE, RATING
WHERE MOVIE.MOVIEID = RATING.MOVIEID
GROUP BY MOVIETITLE;
我需要从我的评级表中确定最低的平均评级,所以我使用了聚合函数
MIN(平均(评级))
但我一直遇到这个错误,我不知道如何解决它:
ORA-00937:没有单一的组功能
我是SQL和Oracle的新手,所以这对我来说都是全新的
编辑
好的,只是澄清一下,在评级表中有多个人对同一部电影进行评级,基本上需要获得每部电影所有评级的平均值,并列出平均值最低的电影。你不能这样做,请尝试将其添加到子查询中
SELECT MOVIETITLE AS "Movie Title", AVG(RATING) AS "AVGRating"
FROM MOVIE, RATING
WHERE MOVIE.MOVIEID = RATING.MOVIEID
GROUP BY MOVIETITLE
HAVING AVG(RATING) =
(
SELECT MIN(AVG(RATING)) AS "AVGRating"
FROM MOVIE, RATING
WHERE MOVIE.MOVIEID = RATING.MOVIEID
GROUP BY MOVIETITLE
)
- 还有另一个
另一种方法(如果有几部电影具有相同的最低评级,
它们将全部显示):
结果:
Movie Title Lowest Average Rating
-------------- ---------------------
Terminator 5,7
如果有一种标准的方法可以在聚合中包含附加值,那就太好了。我发现自己将多个值组合成一个原始值,将这些值进行聚合,然后从聚合中提取原始值:
/* lowest returns a single row */
with lowest as (
select min(
/* combine movieid and avg(rating) into a single raw
* binary value with avg(rating) first so that min(..)
* will sort by rating then by movieid */
utl_raw.overlay(
utl_raw.cast_from_binary_integer(movieid),
utl_raw.cast_from_number(avg(rating)), 5)) packed
from rating group by movieid)
/* extract our rating and movieid from the packed aggregation
* and use it to lookup our movietitle */
select movietitle,
utl_raw.cast_to_number(utl_raw.substr(packed,1,3)) rating
from movie m, lowest l
where m.movieid=
utl_raw.cast_to_binary_integer(utl_raw.substr(packed,5,4))
注意:这假设movieid是int,rating是一个数字(参见sqlfiddle DDL)。如果两者都是整数或数字,您也可以通过将更重要的值向左移动(乘以2的幂)并将它们相加来“打包”它们
计算平均评分,按升序排列,然后取第一个结果
SELECT *
FROM (
SELECT MOVIETITLE AS "Movie Title",
AVG(RATING) AS "Lowest Average Rating"
FROM MOVIE, RATING
WHERE MOVIE.MOVIEID = RATING.MOVIEID
GROUP BY MOVIETITLE
ORDER BY 2 ASC)
WHERE ROWNUM = 1;
如果你也需要电影的标题,我会用一个解析函数来得到最小值。这样你只需要点击每个表一次(其中的解决方案是今 草 顿 웃 将在每个表中点击两次。一次在主选择中,一次在“拥有”选择中)
“最低平均评级”是什么意思?我可以看到一部电影如何有一个最低评级和一个平均评级,但这是两件不同的事情。在评级表中有多个人对同一部电影进行评级,基本上需要得到每部电影所有评级的平均值,并列出平均值最低的电影。这很有趣。它在海量数据上的表现如何?@于是我找到了这个解决方案,必须对海量数据做类似的事情。如果你比较执行计划,你会发现它比这里的其他解决方案更有效,因为评级扫描一次,从电影中检索一行。我欣赏这种方法的独创性,但我相信好代码的一个特点是它易于理解,我不认为它通过了那个测试。@davidardridge完全同意,我认为SQL可以使用一些标准语义来打包和解包以进行聚合。类似于min(评级,movieid).movieid的东西-即使你可以很容易地形成一个元组也不错。在性能损失如此严重的情况下,选择可读性而不是效率是一个艰难的决定。在这种情况下,我会选择评论(我现在会添加一些评论…),如果不需要电影名称,这可能是最好的。这个解决方案唯一的一个问题是,如果你有多个标题具有相同的最低评级。是的。。。在电影评级网站的背景下,这可能不是一个问题,但更多的是关注像“向我展示最低成本的供应商…”或summit之类的东西
/* lowest returns a single row */
with lowest as (
select min(
/* combine movieid and avg(rating) into a single raw
* binary value with avg(rating) first so that min(..)
* will sort by rating then by movieid */
utl_raw.overlay(
utl_raw.cast_from_binary_integer(movieid),
utl_raw.cast_from_number(avg(rating)), 5)) packed
from rating group by movieid)
/* extract our rating and movieid from the packed aggregation
* and use it to lookup our movietitle */
select movietitle,
utl_raw.cast_to_number(utl_raw.substr(packed,1,3)) rating
from movie m, lowest l
where m.movieid=
utl_raw.cast_to_binary_integer(utl_raw.substr(packed,5,4))
SELECT *
FROM (
SELECT MOVIETITLE AS "Movie Title",
AVG(RATING) AS "Lowest Average Rating"
FROM MOVIE, RATING
WHERE MOVIE.MOVIEID = RATING.MOVIEID
GROUP BY MOVIETITLE
ORDER BY 2 ASC)
WHERE ROWNUM = 1;
select movietitle as "Movie Title", avgrating as "Lowest Average Rating"
from (
select
m.movietitle,
avg(r.rating) avgrating,
rank() over (order by avg(rating)) rank
from
movie m
inner join rating r
on r.movieid = m.movieid
group by
m.movietitle
)
where rank = 1;