【问题标题】:Why is my query returning far to many results?为什么我的查询返回很多结果?
【发布时间】:2020-05-04 12:24:20
【问题描述】:

我有一群候选人,他们有过一份或多份工作,每个人都在一家公司工作,使用一些技能。

糟糕的 ascii 艺术如下:

         ---------------                              ---------------   
         | candidate 1 |                              | candidate 2 |
         --------------- \                             --------------      
           /              \                                 |
       -------              --------                        etc
       |job 1|              | job 2 |  
       -------              ---------  
        /     \              /      \  
  ---------   ---------  ---------   --------  
  |company |  | skills | |company | | skills |  
  ---------   ---------  ---------- ----------  

这是我的数据库:

mysql> describe jobs;
+--------------+---------+------+-----+---------+----------------+
| Field        | Type    | Null | Key | Default | Extra          |
+--------------+---------+------+-----+---------+----------------+
| job_id       | int(11) | NO   | PRI | NULL    | auto_increment |
| candidate_id | int(11) | NO   | MUL | NULL    |                |
| company_id   | int(11) | NO   | MUL | NULL    |                |
| start_date   | date    | NO   | MUL | NULL    |                |
| end_date     | date    | NO   | MUL | NULL    |                |
+--------------+---------+------+-----+---------+----------------+

.

mysql> describe candidates;
+----------------+----------+------+-----+---------+----------------+
| Field          | Type     | Null | Key | Default | Extra          |
+----------------+----------+------+-----+---------+----------------+
| candidate_id   | int(11)  | NO   | PRI | NULL    | auto_increment |
| candidate_name | char(50) | NO   | MUL | NULL    |                |
| home_city      | char(50) | NO   | MUL | NULL    |                |
+----------------+----------+------+-----+---------+----------------+

mysql> describe companies;
+-------------------+---------------+------+-----+---------+----------------+

| Field             | Type          | Null | Key | Default | Extra          |
+-------------------+---------------+------+-----+---------+----------------+
| company_id        | int(11)       | NO   | PRI | NULL    | auto_increment |
| company_name      | char(50)      | NO   | MUL | NULL    |                |
| company_city      | char(50)      | NO   | MUL | NULL    |                |
| company_post_code | char(50)      | NO   |     | NULL    |                |
| latitude          | decimal(11,8) | NO   |     | NULL    |                |
| longitude         | decimal(11,8) | NO   |     | NULL    |                |
+-------------------+---------------+------+-----+---------+----------------+

.

mysql> describe skills;
+----------+---------+------+-----+---------+-------+
| Field    | Type    | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+-------+
| skill_id | int(11) | NO   | MUL | NULL    |       |
| job_id   | int(11) | NO   | MUL | NULL    |       |
+----------+---------+------+-----+---------+-------+

.

mysql> describe skill_names;
+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| skill_id   | int(11)  | NO   | PRI | NULL    | auto_increment |
| skill_name | char(32) | NO   | MUL | NULL    |                |
+------------+----------+------+-----+---------+----------------+

这是我对查询的尝试(注意,我打算将通配符更改为字段名称;我只是想让某些东西起作用):

SELECT can.* , co.*, j.*, sn.*
FROM candidates AS can
JOIN jobs AS j 
JOIN companies AS co ON j.company_id = co.company_id
JOIN skills AS s ON s.job_id = j.job_id
JOIN skill_names AS sn ON s.skill_id = s.skill_id

HediSql 说/* Affected rows: 0 Found rows: 34,461,651 Warnings: 0 Duration for 1 query: 0.000 sec. (+ 105.078 sec. network) */

查询有什么问题?我希望从糟糕的 ascii 艺术中清楚我想要达到的目标。

(另外,我加入表格的顺序是否有任何速度差异?我会担心新的 MySql v8 函数稍后将其检索为嵌套 JSON)

【问题讨论】:

  • 其实样本数据对你的问题很有帮助。
  • 以什么方式?我可以发布数据,但它会很幽默(并且是随机生成的)。我很乐意提供帮助,只是确定这会产生怎样的影响,因为对一群候选人的描述,他们有过一份或多份工作,每个人都在一家公司工作,使用一些技能`。
  • 每个表有多少行(至少大约)。
  • 目前?如前所述,大约 100 名候选人拥有大约 5 个工作和大约 3 项技能。在“现实生活”中,可能有 5000 名应聘者,有 10 个工作和 20 种技能。我现在将自动生成更多赎金数据并进行测试。目前在@GMS 的出色回答后 0.16 秒。

标签: mysql sql join query-optimization


【解决方案1】:

您缺少candidatesjobs 之间的连接条件,因此您会得到两个表之间的笛卡尔积。此外,skill_names 上的连接条件存在问题,其中两列相同(这再次生成笛卡尔积)。

SELECT can.* , co.*, j.*, sn.*
FROM candidates AS can
JOIN jobs AS j ON j.candidate_id = can.candidate_id --> here: missing join condition
JOIN companies AS co ON j.company_id = co.company_id
JOIN skills AS s ON s.job_id = j.job_id
JOIN skill_names AS sn ON sn.skill_id = s.skill_id  --> and here: wrong join condition

许多 RDBMS 会在没有 ON 子句的情况下在 JOIN 上引发语法错误(如果你确实想要一个笛卡尔积,你需要使用 CROSS JOIN 来明确它),但是,唉,不是 MySQL .


说到这个问题:

我加入表格的顺序是否有任何速度差异?

没有。只要您使用inner joins(不是left joins),连接顺序对查询规划器来说并不重要,它会按照它认为更有效的顺序重新排列它们。

【讨论】:

  • 73479 rows in set (0.17 sec)哇哦!!我将使用较小的数据库仔细检查查询,但请确保您是正确的,因为您的代表。感谢 1,000,000
  • 我想我会在这里提出 2 个新问题并链接到它们:1)我加入表格的顺序是否会产生任何速度差异(这会提高我的理解)? 2) 新的 MySql v8 函数稍后将其检索为嵌套 JSON 呢
  • @MawgsaysreinstateMonica:更新了我对您的问题的回答 (1)。问题 (2) 需要更多信息,并且可能确实值得提出一个新问题。
  • 一个很好的答案,将来也应该对其他人有所帮助。谢谢你
  • 你能帮我处理一下this new question吗?
猜你喜欢
  • 2011-07-24
  • 1970-01-01
  • 2020-02-03
  • 2017-01-17
  • 1970-01-01
  • 2014-10-07
  • 1970-01-01
  • 2011-11-07
  • 1970-01-01
相关资源
最近更新 更多