【问题标题】:mySQL - SELECT using JOIN, or a nested SELECT (sub-select)?mySQL - 使用 JOIN 选择,还是嵌套选择(子选择)?
【发布时间】:2017-11-01 04:12:29
【问题描述】:

我正在尝试在 mySQL(和 PHP)中编写一个 SELECT,它将检索“图像”表中尚未被某个用户排名的所有行。

这些是我的桌子:

表格:图片

+-----------+----------+-----------+----------+
| Index     | Rank_Good| Rank_OK   | Rank_Bad |
+-----------+----------+-----------+-----------
| 201       | 2        | 9         | 28       |
| 202       | 11       | 20        | 39       |
| 203       | 36       | 14        | 7        |
+-----------+----------+-----------+----------+

表 2:WhoAlreadyClickedImg(没有索引)

+------------+-----------------+-----------+
| ImageIndex | UserWhoRankedIt | RankGiven |
+------------+-----------------+-----------+
| 202        | 87              | OK        |
+------------+-----------------+-----------+
| 202        | 93              | Bad       |
+------------+-----------------+-----------+
| 204        | 93              | Good      |
+------------+-----------------+-----------+
| 203        | 94              | Bad       |
+------------+-----------------+-----------+

每次用户对图像进行排名时,“Images”表都会更新,并且会在“WhoAlreadyClickedImg”表中添加一行。 (这个表没有索引)

例如,如果用户将图像索引 202 排名为“ok”,则 col“Rank_OK”将更新为 (+1),然后将新行添加到“WhoAlreadyClickedImg”表中:

图像索引:201 | UserWhoRankedIt:(使用的会话 id) | RankGiven:好的

我想构建一个不会向已经对其进行排名的用户显示两次相同图像的选择。

例如,如果我是用户“93”,则选择将带来的唯一图像是“203”

更新:

这是我正在使用的查询(@eamonn):

SELECT * FROM Images WHERE Index NOT IN (SELECT ImageIndex FROM WhoAlreadyClickedImg WHERE UserWhoRankedIt = 93);

但我得到一个错误:

您的 SQL 语法有误;检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的“Index NOT IN (SELECT ImageIndex FROM WhoAlreadyClickedImg WHERE UserWhoRankedIt”附近使用正确的语法

我检查了我的系统:

  • 存储引擎:InnoDB

  • MySQL 数据库版本:5.5.33-29.3

  • 现在两个表都有索引 int(11),定义为 PRIMARY,auto_increment

也许有人有想法?

【问题讨论】:

  • 您能否为您的设置转储 SQL,以便我可以在本地环境中调试一下,看看哪里出了问题? Pastebin 是理想的选择。

标签: php mysql select left-join nested-select


【解决方案1】:

那里,这应该可以工作:

SELECT Images.Index 
       FROM Images 
       WHERE Images.Index NOT IN 
             (
                SELECT WhoAlreadyClickedImg.ImageIndex 
                     FROM WhoAlreadyClickedImg 
                     WHERE WhoAlreadyClickedImg.UserWhoRankedIt = 93
             );

记得在列名前加上表名。

【讨论】:

    【解决方案2】:

    SELECT * FROM Images WHERE Index NOT IN (SELECT ImageIndex FROM WhoAlreadyClickedImg WHERE UserWhoRankedIt = 93);

    简单的子查询。

    【讨论】:

    • 我试过了,但是没有用。我什至尝试向 WhoAlreadyClickedImg 表添加索引(如@e4c5 建议的那样)。这是它给我的错误:“您的 SQL 语法有错误;请检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的 'Index NOT IN (SELECT ImageIndex FROM WhoAlreadyClickedImg WHERE UserWhoRankedIt' 附近使用正确的语法"
    【解决方案3】:

    列名Index 是MySQL 中的保留关键字。您应该将 Index 列的名称更改为 Id 或 MainIndex。见此链接:https://dev.mysql.com/doc/refman/5.6/en/keywords.html

    另一种选择是在选择查询中使用表名。例如:

    SELECT * FROM Images WHERE Images.Index NOT IN (SELECT ImageIndex FROM WhoAlreadyClickedImg WHERE UserWhoRankedIt = 93);
    

    我认为您应该重命名您的列,因为这样可以最大限度地减少 SQL 语句出错的机会。

    【讨论】:

    • 获得了由子选择调用的表中的很多行。有时它很慢,有时还可以。 (当我测试它并清空这张桌子时它总是很快) - 有什么建议吗?也许 JOIN 会更好,还是 JOIN 不是解决方案,而选择只是做错了?
    • 您应该在这些列上添加索引:Index、ImageIndex 和 UserWhoRankedIt。它应该可以提高 sql 查询的性能
    • 您的意思是,如果我向“WhoAlreadyClickedMyImg”表添加索引,即使我在查询中完全忽略它,它也会有助于提高速度?怎么样?!
    • 还有——你所说的“为所有这三列添加索引”是什么意思?您的意思是 - 将每个定义为索引?
    • 嗯,是的。为所有三列添加索引。大多数数据库管理工具(例如 phpMyAdmin)都支持添加索引。当您向列添加索引时,数据库服务器会以特殊格式存储该列的内容,从而减少搜索该列所需的时间
    猜你喜欢
    • 2011-05-16
    • 2019-01-06
    • 1970-01-01
    • 2010-12-26
    • 2019-02-28
    • 1970-01-01
    • 2021-07-25
    • 2011-01-02
    • 1970-01-01
    相关资源
    最近更新 更多