【问题标题】:Most efficient JOIN query - MySQL最高效的 JOIN 查询 - MySQL
【发布时间】:2013-10-08 08:11:36
【问题描述】:

下面是我正在工作的 2 个非常大的表的粗略简化。

campaign

|编号 | uid |姓名 |联系方式 |销 |图标 | | 1 | 7 |鲍勃 |泰德 | y6w |哟 | | 2 | 7 |内德 |乔 | y6e | ygy | | 3 | 6 |山姆 |乔恩 | y6t |哎哟|

records

|编号 | uid |西德 |名称 |姓名 |地址 |城市|电话 | | 1 | 7 | 1 |拉尔斯 |杰克| 13 主要 |乐嘉 | 55555 | | 2 | 7 | 1 | rar |乔克 | 10 马翁 | oyjh | 55595 | | 2 | 7 | 1 | ssrs |弗瑞克 | 10 欧 |欧尔| 88595 |

页面循环通过记录表并将结果打印到 HTML 表中。出于某种原因,现有代码对每条记录进行单独查询 "select name from campaign where id = $res['cid']" 我想摆脱第二个查询并进行某种连接,但最有效的方法是什么?

我需要

SELECT * FROM records

还有

SELECT name FROM campaigns WHERE campaigns.id = records.cid

在单个查询中。

我怎样才能有效地做到这一点?

【问题讨论】:

  • 选择 a.name, b.* FROM 活动 a, 记录 b WHERE a.id = b.cid

标签: php mysql sql join


【解决方案1】:

只需连接两个表。您已经具备所需的WHERE 条件。从一列中选择所有列,但从另一列中选择一列。像这样:

SELECT records.*, campaigns.name
FROM records, campaigns
WHERE campaigns.id = records.cid

请注意,没有匹配活动的记录行将会丢失。为避免这种情况,请将您的查询改写如下:

SELECT records.*, campaigns.name
FROM records LEFT JOIN campaigns
ON campaigns.id = records.cid

现在您将获得NULL 名称,而不是丢失的行。

【讨论】:

  • 这正是我目前所拥有的 :) 很高兴知道我在正确的轨道上
  • 等等,不,我的不是左连接
  • "左连接与 ON,而不是 WHERE" -- 想扩展吗?
【解决方案2】:

“最有效”的部分是答案变得非常棘手的地方。一般来说,一个很好的方法是简单地在两个表上编写一个带有连接的查询,然后愉快地跳过唱关于小猫的歌曲。但是,这实际上取决于更多的因素。表有多大,它们是否在查询的正确列上很好地索引?查询运行时,会生成多少条记录?查询中的结果是否按顺序排列?

这就是开始成为一门艺术而不是科学的地方。查看解释计划,了解正在发生的事情,寻找使其更有效或更简单的方法。有时,在 from 子句中运行两个子查询,每个子查询只会生成一个数据子集,这比尝试连接整个表并从中选择所需数据要高效得多。

要更详细地回答这个问题,同时希望对您的特定案例准确无误,需要更多信息。

如果我要在您的数据库中猜测其中的一些内容,如果您的表少于几百万行并且您的数据库性能不错,我建议使用简单的连接进行以下操作。如果您多次重新运行 EXACT 查询,即使是慢速查询也可以很好地被 MySQL 缓存,所以也要看看。我有一个应用程序在一台非常规范的机器上运行,在那里我编写了一个 cron 作业,它只运行一些查询,这些查询带有一夜之间加载的新数据,我所有的用户都认为查询是即时的,因为我确保它们被缓存。有时,真正奏效的是小技巧。

最后,如果您实际上是刚开始使用 SQL 或者不像您认为最终会得到的那样熟悉 - 您可能会使用want to read this Q&A that I wrote,它涵盖了查询的许多基本到中级主题,例如连接,子查询、聚合查询以及更多值得了解的内容。

【讨论】:

  • 一个非常有效的答案,谢谢,但不是很有帮助
  • @Adelphia 不幸的是,根据您提出的问题,很难给您一个全面而准确的答案。查询的效率和速度通常是把几个想法放在一起,运行它们很多次,看看什么效果最好。您很少能简单地查看一个查询并说“如果您……这将是最有效的”,尤其是当您无法查看数据库中的大量细节时。
【解决方案3】:

你可以使用这个查询

SELECT records.*, campaigns.name
FROM records, campaigns
WHERE campaigns.id = records.cid

但是,使用 INNER JOIN(新的 ANSI 标准,ANSI-92)要好得多,因为它更具可读性,并且您可以轻松地将 INNER 替换为 LEFT 或其他类型的连接。

SELECT records.*, campaigns.name
FROM records INNER JOIN campaigns
ON campaigns.id = records.cid

这里有更多解释:

  1. SQL Inner Join. ON condition vs WHERE clause
  2. INNER JOIN ON vs WHERE clause

【讨论】:

    【解决方案4】:
    SELECT *
    FROM records
    LEFT JOIN campaigns
    on records.cid = campaigns.id;
    

    使用左连接而不是内连接可以保证您仍然会列出每个记录条目。

    【讨论】:

    • 左连接使用ON,而不是WHERE。您正在从campaigns 中选择 all 列,这超出了 OP 的要求。由于这可能会将索引查找变成完整的表查找,因此请求过多的数据可能会降低性能。
    • 在我的帖子上回答我对您的帖子的评论可能有点令人困惑。让我们尝试将 cmets 保留在这里……您的原始答案使用关键字 WHERE 表示加入条件,但 Fluffeh 已经在我发布评论后几秒钟编辑了您的答案,因此我的部分评论现在已经过时了。跨度>
    猜你喜欢
    • 2015-05-25
    • 2011-09-03
    • 1970-01-01
    • 2013-11-06
    • 2013-03-22
    • 2016-04-04
    • 2011-09-01
    • 2013-11-13
    • 2018-06-08
    相关资源
    最近更新 更多