我有一个看起来像这样的数据库表
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'
不是这种情况。此表中的所有条目都填充了字段userId
。 userId
字段没有唯一约束。
我正在运行查询以获取符合特定条件的所有健康检查,我还想在获得这些健康检查时返回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
。
答案 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)
我建议以下想法:
在字段Group By
上使用userId
同时应用汇总函数max(id)
进行查询。现在,我们每个max(id)
都有一个userId
。
使用id
上的查询#1的结果加入您的初始表。
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
操作的字段上创建索引。