【问题标题】:MySQL LEFT Join with multiple possibilities and Inner Join具有多种可能性的 MySQL LEFT Join 和 Inner Join
【发布时间】:2015-07-18 09:40:44
【问题描述】:

不知道有没有被问过类似的问题,但是我在stackoverflow的mysql上看了一个多小时

我的问题是,我有多个表,我需要在 mysql 中使用左连接和内连接来加入它们

实体表:

id (key) | entityName

1        |   john
2        |   harris
3        |   henry
4        |   mark
5        |   dom

活动表

id (key) | entityID  | status

1        |       1   |   1
2        |       2   |   0
3        |       4   |   1

地理数据表

id (key) | entityID  | moment (timestamps when the entry was done)

1        |       1   | 1429542320 (smaller)
2        |       1   | 1429542331 (bigger)
3        |       2   | 1429542320 (smaller)
4        |       2   | 1429542331 (biger)
5        |       4   | 1429542331 (bigger)

信息表

id (key) | entityID | infos | date 

   1     |      1   |  xxx  |   today
   2     |      1   |  xxx  |   yesterday
   3     |      2   |  xxx  |   today
   4     |      2   |  xxx  |   yesterday
   5     |      3   |  xxx  |   yesterday
   6     |      5   |  xxx  |   today
   7     |      5   |  xxx  |   yesterday
   8     |      5   |  xxx  |   tomorrow

所以基本上,我需要每个拥有今天信息的实体 此外,如果他们的状态为真(或 1)(来自活动表),请在地理数据表中显示他们的日期。

所以这就是我所拥有的:

SELECT e.id, 
       e.entityName, 
       i.infos, 
       a.status, 
       MAX(g.moment) -- but the max only if status =1 
  FROM entities AS e
  LEFT JOIN activity AS a ON a.entityID = e.id
  LEFT JOIN geodata AS g ON g.entityID = e.id
 INNER JOIN infos AS i ON e.id = i.entityID
 WHERE i.date = 'today'
 GROUP BY e.id

我希望每个实体都有关于今天的信息,但其中一些也有活动,所以我想显示它(如果它不只是让左连接放 NULL)如果状态为 0,我不'不需要那一刻,但如果它是真的,我只需要更大的一个(它的数字,所以 Max() 应该这样做但它会中断)

预期结果是:

id (key) | entityName | infos |   status |   MAX(moment) | ..other columns

   1     |     john   |  xxx  |      1   | 1429542331 (the bigger one)
   2     |     harris |  xxx  |      0   | NULL
   5     |     dom    |  xxx  |     NULL | NULL

如果有人可以帮助我,我将非常感激 :) PS:对不起,我的英语不是我的母语

【问题讨论】:

    标签: mysql sql join left-join inner-join


    【解决方案1】:

    你可以改变 MAX(g.moment)IF(a.status<>1, NULL, MAX(g.moment))

    或者将LEFT JOIN geodata AS g ON g.entityID = e.id更改为LEFT JOIN geodata AS g ON a.entityID = e.id AND a.status = 1

    哪个更快可能取决于您的实际数据;第二个可能会更快,因为连接的记录更少,但它使用的更复杂的连接条件可能会减慢连接速度。

    【讨论】:

    • 成功了!但这花了很多时间。第一种方法大约需要 20 秒,第二种方法大约需要 7 秒。考虑到我在加载 php 页面时触发了这个查询,它真的很长。我在每个表中只有大约 2k 数据,而且我知道它会增长。有没有更快的方法?
    • 您的表是否正确编入索引? (应该在所有表上都有索引:infos.date、entityID,但地理数据表应该在 entityID,status 上按此顺序有一个索引。)
    • 另外,由于我并不总是信任查询优化器,您可能需要重新排列 JOIN,以便 infos 成为第一个表。
    • 我做了,大约花了 1.4 秒。谢谢你们!
    • 添加了索引还是重新排列了连接顺序?
    猜你喜欢
    • 1970-01-01
    • 2023-03-17
    • 2018-07-10
    • 2016-12-14
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    • 2013-02-07
    • 2021-11-21
    相关资源
    最近更新 更多