我有两张桌子。 uploads
和profits
。
上传:
╔════╦══════════════╦══════════════════╗
║ id ║ name ║ more columns... ║
╠════╬══════════════╬══════════════════╣
║ 1 ║ Jeff Atwood ║ ................ ║
║ 2 ║ Geoff Dalgas ║ ................ ║
║ 3 ║ Jarrod Dixon ║ ................ ║
║ 4 ║ Joel Spolsky ║ ................ ║
╚════╩══════════════╩══════════════════╝
利润:
╔══════════╦══════════════╦══════════════════╗
║ uploadid ║ amount ║ more columns... ║
╠══════════╬══════════════╬══════════════════╣
║ 1 ║ 4.0 ║ ................ ║
║ 1 ║ 7.2 ║ ................ ║
║ 3 ║ 6.3 ║ ................ ║
║ 4 ║ 2.5 ║ ................ ║
╚══════════╩══════════════╩══════════════════╝
如您所见,uploads
。id
=> profits
。uploadid
我想显示uploads
表中的一些行,还有一列可以告诉我有多少"利润"有。。
结果示例:
╔════╦══════════════╦════════════════╦══════════════════╗
║ id ║ name ║ profitsCount ║ more columns... ║
╠════╬══════════════╬════════════════╬══════════════════╣
║ 1 ║ Jeff Atwood ║ 2 ║ ................ ║
║ 2 ║ Geoff Dalgas ║ 0 ║ ................ ║
║ 3 ║ Jarrod Dixon ║ 1 ║ ................ ║
║ 4 ║ Joel Spolsky ║ 1 ║ ................ ║
╚════╩══════════════╩════════════════╩══════════════════╝
注意:在实际表中,uploads
。id
和profits
。uploadid
列为varchar
而非int
,我在这里做int
更清楚。
问题是,当我使用大表(数千行)运行查询时,需要大量时间
我的查询:
SELECT `uploads`.* ,COUNT(`profits`.`uploadid`) AS `numProfits`
FROM `uploads`
LEFT JOIN `profits`
ON `uploads`.`id` = `profits`.`uploadid`
GROUP BY `uploads`.`id`
ORDER BY `numProfits`
DESC
LIMIT 30
答案 0 :(得分:2)
这是您的查询:
SELECT u.* ,COUNT(p.uploadid) AS numProfits
FROM uploads LEFT JOIN
profits p
ON u.id = p.uploadid
GROUP BY u.id
ORDER BY numProfits DESC
LIMIT 30;
第一项改进:在profits(uploadid)
上创建索引。这可能会解决您的问题。您可以通过以下方式获得更好的性能:
select u.*,
(select count(*) from profits p where u.id = p.uploadid) as numProfits
from uploads u
order by numProfits desc
limit 30;
这消除了对文件排序聚合的需要。我更喜欢带有显式聚合的第一个版本,但子查询可以更好地工作。
您还可以在子查询中尝试聚合:
select u.*, numProfits
from uploads u join
(select uploadid, count(*) as numProfits
from profits p
group by uploadid
order by numProfits desc
limit 30
) p
on u.id = p.uploadid;
order by numProfits desc;
编辑:
对于最后一个解决方案,要选择甚至没有利润的行,请使用left join
和coalesce()
:
select u.*, coalesce(numProfits, 0) as numProfits
from uploads u left join
(select uploadid, count(*) as numProfits
from profits p
group by uploadid
order by numProfits desc
limit 30
) p
on u.id = p.uploadid;
order by numProfits desc;
答案 1 :(得分:-2)
您可以通过按字段索引顺序来最小化SQL选择查询时间,这可能(并且将会)影响您的插入时间(并且只要索引列受到影响就会更新)