不是那么简单的 SQL 查询
Posted
技术标签:
【中文标题】不是那么简单的 SQL 查询【英文标题】:Not so simple SQL queries 【发布时间】:2013-01-19 22:00:05 【问题描述】:所以我得到了任务,即使在 Google 的帮助下我仍然无法解决一些问题。也许有人可以提出一些解决方案(是否必须使用 JOINS 来完成?等等)。
这是数据库:
CREATE TABLE Foto (
ID int PRIMARY KEY,
FileName varchar(100),
FileSize int,
Created int
) DEFAULT CHARSET=utf8;
CREATE TABLE Users (
LoginName varchar(10) PRIMARY KEY,
Surname varchar(20),
Name varchar(20),
Created date,
LastLoginDate date
) DEFAULT CHARSET=utf8;
CREATE TABLE Scoring (
ID int,
LoginName varchar(10),
Score int,
ScoreDate date,
FOREIGN KEY (LoginName) REFERENCES Users(LoginName),
FOREIGN KEY (ID) REFERENCES Foto(ID),
PRIMARY KEY(ID, LoginName)
) DEFAULT CHARSET=utf8;
“照片”(照片)和用户表应该很清楚。 “评分”表适用于对照片进行评分的用户。每个用户只能对每张照片进行一次评分。任务是:
编写查询,返回所有 AVG 分数高于 9 的照片的照片 ID、文件名和 AVG(Score),并创建可提高此查询性能的索引。
编写查询以返回“登录名”、“姓名”、“姓氏”以及用户对他为特定用户(例如,名为“John”的用户)评分的照片给出的 AVG 分数)。创建可提高此查询性能的索引。
我使用的是 mysql 5.5.16,我对第一个查询的想法是这样的:
SELECT F.ID, F.FileName, AVG(SC.Score)
FROM Foto F, scoring SC
WHERE F.ID = SC.ID
AND AVG(SC.Score) > 9
GROUP BY SC.ID;
它返回“#1111 - 组函数的无效使用”,我从不喜欢聚合函数:D
总体而言,我意识到我很擅长 SQL,并且我想训练更多地编写查询,但是我在互联网上找到的大多数教程都有非常简单的示例,对解决这些问题没有多大帮助。也许你们中的一些人可以向我建议一个资源,该资源将具有更复杂、准备好的数据库和任务(如果我遇到困难,也有答案)来编写查询?
【问题讨论】:
你需要使用HAVING mysqltutorial.org/mysql-having.aspx 感谢和 +1 想要学习 :-) 【参考方案1】:WHERE 子句用于比较基表中的值,而 HAVING 子句可用于过滤聚合的结果 查询结果集中的函数。
HAVING 子句被添加到 SQL,因为 WHERE 关键字不能 与聚合函数一起使用。
(1)
您必须将HAVING
添加到您的查询中。
SELECT F.ID, F.FileName, AVG(SC.Score)
FROM Foto F INNER JOIN scoring S ON F.ID = S.ID
GROUP BY F.ID, F.FileName
HAVING AVG(S.Score) > 9
(2)
SELECT U.LoginName, U.Name, U.Surname, AVG(S.Score)
FROM Scoring S INNER JOIN Users U ON S.LoginName = U.LoginName
GROUP BY S.LoginName
SQLFiddle Demo
希望这个答案能给你下次考试更好的背景:)
【讨论】:
感谢你们所有人的快速而有帮助的回复! :) @JustABoy - 很高兴随时提供帮助 :)【参考方案2】:可能有帮助的一件事是学习使用显式 JOIN 语法(使用 ON
子句)而不是老式的隐式语法(使用 WHERE
子句`)。这应该有助于您将来更清楚地了解情况。
您的错误是您需要使用HAVING
子句来对聚合函数的结果进行子集化。您不能在 WHERE
子句中使用聚合函数。
所以,试试这个吧:
SELECT F.ID
, F.FileName
, AVG(SC.Score)
FROM Foto F
JOIN scoring SC
ON F.ID = SC.ID
GROUP BY F.ID, F.FileName
HAVING AVG(SC.Score) > 9
祝你好运!
编辑:了解任何数据库的最佳地点是您正在使用的特定数据库的文档页面。在你的情况下,look here。
【讨论】:
【参考方案3】:选择中的所有内容都必须在 GROUP BY 或聚合函数中。
SELECT F.ID, F.FileName, AVG(SC.Score)
FROM Foto F
INNER JOIN scoring SC
ON F.ID = SC.ID
GROUP BY F.ID, F.FileName
HAVING AVG(SC.Score) > 9
您将要加入或搜索的任何列都可以从索引中受益。
【讨论】:
MySQL 不会自动进行 GROUP BY 吗?我认为问题只是在 WHERE 子句中使用 AVG。 是的,但那是 MySQL 的偏差,它不属于“标准 SQL”的一部分,所以如果你以这种方式学习它,当你继续使用 SQL Server、Oracle 等时它将无法工作. 是的,但是“选择中的所有内容都必须在 GROUP BY 或聚合函数中。”不是真的,它不一定是。它应该是。 这不仅适用于 MySQL,而且 MySQL 给你的是一个“样本”。你可以使用它,我只是认为这是一种不好的做法,尤其是在你学习的时候。 其实它是(SQL 2003+)标准的一部分。如果列在功能上依赖于分组列,则可以在HAVING
和SELECT
子句中使用。 (MySQL 当然不做任何这样的依赖检查,并且可以允许不遵循这个的查询)。不过,在这种特殊情况下,OP 的查询很好,并且遵循 (SQL 2003) 标准。以上是关于不是那么简单的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章
Mybatis 中的 PreparedStatement 预编译,不是你想的那么简单!
用SQL完成查询,设有一个简单的教学管理数据库,其关系模式为: