SQL:以AVG为条件时,没有给出正确的输出的情况

问题描述

我有一个唯一用户表,每个用户都有一个“评分”列(这是他们在不同评论表中给出的所有评分中给出的平均评分)。我想在表中添加另一列,该列指定他们给出的评分高于所有用户的所有评分的平均值(因此我使用AVG()函数),低于或平均(我称其为“偏见” )。换句话说,我想查看每个用户给出的平均评分是否高于总平均值。我了解此查询的局限性,并且理想情况下,我会包含一个间隔(即低于或高于平均值0.5个点内仍算作平均值),但即使是最简单的查询也无法工作。

我一直在使用Coursera课程中的Yelp数据集,但是我尝试创建一个示例,该示例产生的结果与我不希望的相同-仅一行。我想对每一行进行这种分类,因此在此示例中,它应该返回3行,前两行“低于平均水平”,第三行“高于平均水平”。但是,下面的代码仅产生一行。我一直在使用R,这似乎是我使用了错误的语法,但是在网上搜索30分钟后,我找不到解决方案。

我正在工作,并且希望在Coursera中将sqlite语法用作课程的一部分

CREATE TABLE test 
    (
     id integer primary key,rating integer
    );

INSERT INTO test
(id,rating)
VALUES
(1,1);

INSERT INTO test
(id,rating)
VALUES
(2,3);

INSERT INTO test
(id,rating)
VALUES
(3,8);

SELECT id,rating,CASE
    WHEN rating > AVG(rating) THEN "above average"
    WHEN rating < AVG(rating) THEN "below average"
    ELSE "no bias"
   END AS "bias"
FROM test

解决方法

您不能像这样使用聚合函数AVG()
但是您可以使用AVG()窗口函数来做到这一点:

SELECT id,rating,CASE
    WHEN rating > AVG(rating) OVER () THEN "above average"
    WHEN rating < AVG(rating) OVER () THEN "below average"
    ELSE "no bias"
   END AS "bias"
FROM test

请参见demo
结果:

| id  | rating | bias          |
| --- | ------ | ------------- |
| 1   | 1      | below average |
| 2   | 3      | below average |
| 3   | 8      | above average |
,
SELECT id,CASE
    WHEN rating > (select AVG(rating) from test) THEN "above average"
    WHEN rating < (select AVG(rating) from test) THEN "below average"
    ELSE "no bias"
   END AS "bias"
FROM test

AVG是一个聚合函数,与GROUP BY结合使用。 当您在GROUP BY部分中未指定任何内容时,它将汇总整个表,从而将其减少为一行。

通常,您选择汇总列和非汇总列,而不在GROUP BY列表中指定非汇总列。我不是允许这种行为的DBMS的忠实拥护者(SQLLite似乎是一个冒犯者)。

我在上面的查询中所做的是我使用子查询计算了整个表的平均值。然后将每一行与平均值进行比较。

或者像其他人指定的那样,您可以使用WINDOW函数。在窗口定义的数据的某些部分上应用函数的位置。它们看起来像常规的聚合函数组件,但是您会注意到OVER关键字,它们指定将它们应用于窗口。在over子句中,您可以对数据进行分区,也可以将其整体使用。例如,如果您有多个商店并且每个商店每天都有销售量,则可以按商店进行分区以计算每个商店的平均值。