MySQL加入非唯一标识符

时间:2016-03-08 20:44:41

标签: mysql join

我有一个看起来像这样的数据库表

apiRequest table:

+-------+-------------+--------------------------------------+----------------+
| id    |    type     |                   userId             |     device     |
+-------+-------------+--------------------------------------+----------------+
| 26786 | healthcheck | 7B0BEA35-7D09-4D46-99C0-45EFF7D3F6E8 | NULL           |
| 26788 | root        | 7B0BEA35-7D09-4D46-99C0-45EFF7D3F6E8 | iPhone 6S Plus |
| 26789 | healthcheck | 7B0BEA35-7D09-4D46-99C0-45EFF7D3F6E8 | NULL           |
| 26791 | root        | 7B0BEA35-7D09-4D46-99C0-45EFF7D3F6E8 | iPhone 6S Plus |
| 26792 | healthcheck | 7B0BEA35-7D09-4D46-99C0-45EFF7D3F6E8 | NULL           |
| 26794 | healthcheck | 7B0BEA35-7D09-4D46-99C0-45EFF7D3F6E8 | NULL           |
| 26795 | root        | 054D45BF-8C0D-40D9-9917-12C86C9A1C09 | iPhone 5       |
| 26796 | root        | 054D45BF-8C0D-40D9-9917-12C86C9A1C09 | iPhone 5       |

在设备字段中存在type = 'root'值的所有请求中,type = 'healthcheck'不是这种情况。此表中的所有条目都填充了字段userIduserId字段没有唯一约束。

我正在运行查询以获取符合特定条件的所有健康检查,我还想在获得这些健康检查时返回device,为此,我需要匹配来自userId的{​​{1}}来自healthcheck条目的userId的{​​{1}}条目。

下面是一个有效的SQL查询,虽然它需要很长时间才能运行,因此无法使用:

root

它返回所需的结果:

SELECT a.id, a.type, a.userId, b.device 
FROM apiRequest a 
INNER JOIN apiRequest b ON b.userId = a.userId 
WHERE a.type = 'healthcheck' 
AND b.id = ( SELECT max(id) FROM apiRequest c WHERE c.userId = a.userId AND c.type='root' );

我尝试过运行| 26749 | healthcheck | 054D45BF-8C0D-40D9-9917-12C86C9A1C09 | iPhone 5 | | 26750 | healthcheck | 054D45BF-8C0D-40D9-9917-12C86C9A1C09 | iPhone 5 | | 26752 | healthcheck | 054D45BF-8C0D-40D9-9917-12C86C9A1C09 | iPhone 5 | | 26755 | healthcheck | 7B0BEA35-7D09-4D46-99C0-45EFF7D3F6E8 | iPhone 6S Plus | | 26758 | healthcheck | 7B0BEA35-7D09-4D46-99C0-45EFF7D3F6E8 | iPhone 6S Plus | | 26762 | healthcheck | 7B0BEA35-7D09-4D46-99C0-45EFF7D3F6E8 | iPhone 6S Plus | ,但因为左表(类型LEFT JOIN on userId)中的每个条目的右表(类型为root)都有很多匹配项没有返回我需要的结果。

我的目标:

是找到性能最佳的查询来选择healthcheck类型的所有条目,并在healthcheck类型的条目中包含匹配的device

2 个答案:

答案 0 :(得分:1)

使用此查询可能会获得更好的性能,因为子选择只需要评估一次:

SELECT      a.id, a.type, a.userId, b.device 
FROM        apiRequest a 
LEFT JOIN  (SELECT   userId, MAX(device) device 
            FROM     apiRequest
            WHERE    type = 'root'
            GROUP BY userId) b ON b.userId = a.userId 
WHERE       a.type = 'healthcheck'

但请确保在(type,userId,device)上定义了非唯一索引。这可以通过以下声明来完成:

CREATE INDEX idx_apirequest_user_device ON apiRequest (type, userId, device);

答案 1 :(得分:0)

我建议以下想法:

  1. 在字段Group By上使用userId同时应用汇总函数max(id)进行查询。现在,我们每个max(id)都有一个userId

  2. 使用id上的查询#1的结果加入您的初始表。

  3. SQL代码

    select a.id, a.type, a.userId, b.device
    from apiRequest a
    inner join apiRequest b on a.userId = b.userId
    inner join  (select max(id) id, userId
                 from apiRequest
                 where type = 'root'
                 group by userId) as c
    on b.id = c.id
    where a.type = 'healthcheck'
    

    它与您的示例不同,但由于没有子选择请求,因此运行速度更快。

    还考虑在参与join操作的字段上创建索引。