不是那么简单的 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+)标准的一部分。如果列在功能上依赖于分组列,则可以在HAVINGSELECT 子句中使用。 (MySQL 当然不做任何这样的依赖检查,并且可以允许不遵循这个的查询)。不过,在这种特殊情况下,OP 的查询很好,并且遵循 (SQL 2003) 标准。

以上是关于不是那么简单的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

SQL问题求助,查询结果如何清除NULL的空值

Mybatis 中的 PreparedStatement 预编译,不是你想的那么简单!

用SQL完成查询,设有一个简单的教学管理数据库,其关系模式为:

java jdbc 的sql语句、 根据时间查询表中数据、若有数据那么更新数据 如果没有数据、那么

jsonjs数组真心不是想得那么简单

如何让SQL成为你很好的查询工具