SQLite AVG() 返回与行相同的结果

Posted

技术标签:

【中文标题】SQLite AVG() 返回与行相同的结果【英文标题】:SQLite AVG() returns same result as row 【发布时间】:2018-12-02 20:35:11 【问题描述】:

在使用AVG() 计算学生的平均分时,我注意到我的结果与每行输入的结果相同。

例如:

在上图中,Jeff 的第 2 学期和第 3 学期有 8385,但他的 avg_mark 不是显示 83.5 的单行

我的查询如下:

Select m.stdName, m.markPercent, m.crsName, m.term, AVG(distinct markPercent)  as avg_mark 
from Marks as m 
inner join StudentSchedule as ss on ss.crsName = m.crsName and ss.stdName = m.stdName
Inner JOIn Course as c on c.crsName = m.crsName
where m.stdName like 'Jeff'
group by m.stdName, m.markPercent, m.crsName, m.term;

我的架构中的一些表:

create table Course (
  crsID INTEGER PRIMARY KEY  AUTOINCREMENT,
  crsName VARCHAR(8) NOT NULL,
  crsTerm INT NOT NULL
);

CREATE TABLE StudentSchedule(
  stdSchedule INTEGER PRIMARY KEY  AUTOINCREMENT,
  stdName INT NOT NULL,
  teacherName INT not NULL,
  crsName INT not NULL,
  startTime NUMERIC NOT NULL,
  endTime NUMERIC NOT NULL,
  term INT NOT NULL,
  FOREIGN KEY(stdName) references Student(stdID),
  FOREIGN KEY(teacherName) REFERENCES Teacher(teacherID),
  FOREIGN KEY(crsName) REFERENCES Course(crsID)
);

CREATE TABLE Marks (
  markID  INTEGER PRIMARY KEY AUTOINCREMENT,
  markPercent REAL NOT NULL,
  stdName INT NOT NULL,
  crsName INT not NULL,
  term INT NOT NULL,
  FOREIGN KEY(stdName) references Student(stdID),
  FOREIGN KEY(crsName) REFERENCES Course(crsID),
  FOREIGN KEY(term) references StudentSchedule(term)
);

insert into Course (crsName, crsTerm) values ('COMP4900', 2);

insert into StudentSchedule(stdName, teacherName, crsName, startTime, endTime, term) values ('Jeff','tej','COMP4900',1000,1200,2);
insert into StudentSchedule(stdName, teacherName, crsName, startTime, endTime, term) values ('Jeff','farnaz','COMP4900',1200,200,3);

insert into Marks (markPercent, stdName, crsName, term) values (83.0, 'Jeff','COMP4900', 2);
insert into Marks (markPercent, stdName, crsName, term) values (87.0, 'Jeff','COMP4900', 3);

谁能指出我的查询中的缺陷?

【问题讨论】:

【参考方案1】:

数据有点混乱,因为 stdNamecrsName 是整数,但您的 INSERT 将字符串放入其中(不幸的是,SQLite 让您侥幸逃脱)。

除此之外,主要问题是您按m.markPercent 和其他几项内容进行分组,因此您最终一次将聚合函数应用于一行。还有奇怪的AVG(distinct markPercent) 没有多大意义,GROUP BY 问题隐藏了这个问题。

您最好在派生表中建立平均值并加入该表。您所追求的平均值可以通过以下方式计算:

select stdName, avg(markPercent) avgMark
from Marks
group by stdName, crsName

你在每门课程中追求学生的平均水平,这正是它所说的。将其用作派生表并加入它:

select m.stdName, m.markPercent, m.crsName, m.term, a.avgMark
from Marks m
join (select stdName, avg(markPercent) avgMark from Marks group by stdName, crsName) a on m.stdName = a.stdName
where ...

然后,如果stdNamecrsName 确实是引用其他表的整数,那么更多的连接以获得您想要的实际字符串名称。

【讨论】:

您还可以指出AVG(DISTINCT) 基本上永远不会是正确的做法。 @GordonLinoff 没错,我错过了那个。

以上是关于SQLite AVG() 返回与行相同的结果的主要内容,如果未能解决你的问题,请参考以下文章

SQL语句对返回的结果集里的字段再进行条件查询,在一个结果集显示

SQL AVG 返回一个 int

在 SQL 查询中使用 avg() 函数只返回一行?

SQL AVG OVER 所有观察结果

SQL中的函数以及实例

Sql Service的艺术 SQL聚合函数的应用