Mysql子查询还是php处理?

时间:2012-08-27 04:51:28

标签: php mysql subquery post-processing

我的查询类似于:

Select 
    tradesmen.id,
    (SELECT COUNT(quotes.id) FROM quotes WHERE quotes.tradesman_id = tradesmen.id) AS quoted
From
    tradesmen;

所以基本上数据库中的每一行都有一个子查询(50,000+)。 现在每个商人可能会有大约1,000到2,000个报价。

所以我可以使用这个子查询来计算它们。

或者,

我可以进行查询以获得所有商人。

select tradesman.id from tradesmen;

执行一次查询以获取所有引号计数

select tradesman_id as id, count(quotes.id) as quotes from quotes group by tradesman_id;

然后遍历每个商人并从数组中拉出每个商人的计数。

mysql的速度有多快?第二种方法会提供显着的好处,还是两种方法都可以接受?

一般参考我的实际查询是:

SELECT 
    tradesmen.*, 
    regions.name AS region_name, 
    GROUP_CONCAT(ptypes_tradesmen.ptype_id SEPARATOR '|') AS ptype_ids, 
    (SELECT 
         COUNT(quotes.id) 
     FROM 
         quotes 
     WHERE 
         quotes.tradesman_id = tradesmen.id
    ) AS quoted, 
    (SELECT 
         COUNT(quote_intentions.id) 
     FROM 
         quote_intentions 
     WHERE 
         quote_intentions.tradesman_id = tradesmen.id
    ) AS intended, 
    (SELECT 
         COUNT(quotes.id) FROM quotes 
     WHERE 
         quotes.tradesman_id = tradesmen.id 
         AND quotes.accepted = 1
    ) AS awarded
FROM 
    (`tradesmen`)
LEFT JOIN `regions` ON `regions`.`id` = `tradesmen`.`region_id`
LEFT JOIN `ptypes_tradesmen` ON `ptypes_tradesmen`.`tradesman_id` = `tradesmen`.`id`
GROUP BY `tradesmen`.`id`

更新

使用ctrahey的答案我改变了查询。

所以,我们现在有三个版本的查询..

ctraheys:

SELECT 
    tradesmen.*, 
    regions.name AS region_name, 
    GROUP_CONCAT(ptypes_tradesmen.ptype_id SEPARATOR '|') AS ptype_ids, 
    COUNT(quotes.id) AS quoted,
    COUNT(quote_intentions.id) AS intended,
    COUNT(NULLIF(quotes.accepted, 0)) AS awarded
FROM (`tradesmen`)
LEFT JOIN `regions` ON `regions`.`id` = `tradesmen`.`region_id`
LEFT JOIN `ptypes_tradesmen` ON `ptypes_tradesmen`.`tradesman_id` = `tradesmen`.`id`
LEFT JOIN quotes ON quotes.tradesman_id = tradesmen.id
LEFT JOIN quote_intentions ON quote_intentions.tradesman_id = tradesmen.id
GROUP BY `tradesmen`.`id`

我的修改版本:

SELECT 
    t.*, 
    r.name AS region_name, 
    GROUP_CONCAT(p.ptype_id SEPARATOR "|") AS ptype_ids, 
    COUNT(q.id) as quoted, 
    COUNT(i.id) as intended, 
    COUNT(NULLIF(q.accepted, 0)) as awarded
FROM (tradesmen t)
LEFT JOIN regions r ON r.id = t.region_id
LEFT JOIN quotes q ON t.id = q.tradesman_id
LEFT JOIN quote_intentions i ON t.id = i.tradesman_id
LEFT JOIN ptypes_tradesmen p ON p.tradesman_id = t.id
GROUP BY t.id

原文:

SELECT 
    tradesmen.*, 
    regions.name AS region_name, 
    GROUP_CONCAT(ptypes_tradesmen.ptype_id SEPARATOR '|') AS ptype_ids, 
    (SELECT 
         COUNT(quotes.id) 
     FROM 
         quotes 
     WHERE 
         quotes.tradesman_id = tradesmen.id
    ) AS quoted, 
    (SELECT 
         COUNT(quote_intentions.id) 
     FROM 
         quote_intentions 
     WHERE 
         quote_intentions.tradesman_id = tradesmen.id
    ) AS intended, 
    (SELECT 
         COUNT(quotes.id) FROM quotes 
     WHERE 
         quotes.tradesman_id = tradesmen.id 
         AND quotes.accepted = 1
    ) AS awarded
FROM 
    (`tradesmen`)
LEFT JOIN `regions` ON `regions`.`id` = `tradesmen`.`region_id`
LEFT JOIN `ptypes_tradesmen` ON `ptypes_tradesmen`.`tradesman_id` = `tradesmen`.`id`
GROUP BY `tradesmen`.`id`

虽然它们都返回了几乎相同的结果,但最后四个字段存在差异(因此我将从结果数组中删除所有其他行)。

从原始查询(正确结果):

array('id' => '53',
  'ptype_ids' => '58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68',
  'quoted' => '6',
  'intended' => '14',
  'awarded' => '3'),

来自ctrahey的查询:

array('id' => '53',
  'ptype_ids' => '58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|58|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|2|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|7|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|17|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|40|40|40|40|40|4',
  'quoted' => '2016',
  'intended' => '2016',
  'awarded' => '1008'),

来自我修改过的查询:

array('id' => '53',
  'ptype_ids' => '58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68|58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68|58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68|58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68|58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68|58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68|58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68|58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68|58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68|58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68|58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68|58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68|58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68|58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68|58|2|7|17|1|40|52|4|74|66|19|15|46|13|67|8|75|59|23|9|31|71|24|68|58|2|7|17|1|40|52|4|74|66|19|15|46',
  'quoted' => '2016',
  'intended' => '2016',
  'awarded' => '1008'),

1 个答案:

答案 0 :(得分:5)

既不!做一个正确的JOIN(RDBMS中的实际值是):

SELECT 
  tradesmen.id,
  COUNT(quotes.id) as quoted
FROM 
  tradesmen
  LEFT JOIN quotes ON quotes.tradesman_id = tradesmen.id
GROUP BY tradesmen.id

此查询将正是您所需要的并且快速闪电!

编辑您的真实查询

真实查询中唯一需要注意的是接受引号计数中的NULLIF位,因为(IIRC)COUNT()计数false / 0,但不是NULL。

SELECT 
    tradesmen.*, 
    regions.name AS region_name, 
    GROUP_CONCAT(ptypes_tradesmen.ptype_id SEPARATOR '|') AS ptype_ids, 
    COUNT(quotes.id) AS quoted
    COUNT(quote_intentions.id) AS intended
    COUNT(NULLIF(quotes.accepted, 0)) AS awarded
FROM (`tradesmen`)
LEFT JOIN `regions` ON `regions`.`id` = `tradesmen`.`region_id`
LEFT JOIN `ptypes_tradesmen` ON `ptypes_tradesmen`.`tradesman_id` = `tradesmen`.`id`
LEFT JOIN quotes ON quotes.tradesman_id = tradesmen.id
LEFT JOIN quote_intentions ON quote_intentions.tradesman_id = tradesmen.id
GROUP BY `tradesmen`.`id`