Mysql子查询还是php处理?

Mysql子查询还是php处理?,php,mysql,subquery,post-processing,Php,Mysql,Subquery,Post Processing,我有一个类似以下内容的查询: Select tradesmen.id, (SELECT COUNT(quotes.id) FROM quotes WHERE quotes.tradesman_id = tradesmen.id) AS quoted From tradesmen; 所以基本上数据库中的每一行都有一个子查询(50000+)。 现在每个商人的报价可能在1000-2000左右 所以我可以使用这个子查询来计算它们 或者 我可以做这个查询来找到所有的商人 sel

我有一个类似以下内容的查询:

Select 
    tradesmen.id,
    (SELECT COUNT(quotes.id) FROM quotes WHERE quotes.tradesman_id = tradesmen.id) AS quoted
From
    tradesmen;
所以基本上数据库中的每一行都有一个子查询(50000+)。 现在每个商人的报价可能在1000-2000左右

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

或者

我可以做这个查询来找到所有的商人

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`
虽然它们都返回几乎相同的结果,但最后四个字段存在差异(因此,我将从这里的结果数组中删除所有其他行)

来自原始查询(正确结果):

根据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'),
都不是!进行适当的联接(RDBMS中的实际值为):

这个查询正是您所需要的,而且很快就会变亮

编辑您的真实查询 在实际查询中需要注意的唯一一点是接受引号计数内的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`
都不是!进行适当的联接(RDBMS中的实际值为):

这个查询正是您所需要的,而且很快就会变亮

编辑您的真实查询 在实际查询中需要注意的唯一一点是接受引号计数内的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`


我喜欢这个答案,是的,对于一个简单的查询,比如我的示例,这很好,我已经在上面添加了我的实际查询,在这种情况下你会如何应用它?使用相同的基本结构。这就像“给某人加入”和“教某人加入”。。。你的问题对于地区和类型的商人有正确的想法,只需应用你在那里看到的以及你的简单示例和我的答案之间的差异…:D我正要发表评论说,对了,除了获奖部分之外,我所有的东西都在运行连接:D这是我为什么要分享它的主要原因;这有点“抓住你了”。干杯请看我的更新,查询正在生成不同的结果。我喜欢答案,是的,对于像我的示例这样的简单查询,这很好,我已经在上面添加了我的实际查询,在这种情况下,您将如何应用它?使用相同的基本结构。这就像“给某人加入”和“教某人加入”。。。你的问题对于地区和类型的商人有正确的想法,只需应用你在那里看到的以及你的简单示例和我的答案之间的差异…:D我正要发表评论说,对了,除了获奖部分之外,我所有的东西都在运行连接:D这是我为什么要分享它的主要原因;这有点“抓住你了”。干杯请参阅我的更新,查询正在生成不同的结果。第一个想法:将DISTINCT添加到每个COUNT()子句中:
COUNT(DISTINCT quotes.id)as quoted
(目前,每个连接行都有一个连接,其中有四个连接,因此可能会有很多额外的行。DISTINCT应该将其缩减。抱歉,该注释似乎被截断了…抱歉,我在何处将DISTINCT添加到授予的
计数(NULLIF(q.accepted,0))
啊,得到了,在quotes表上进行了另一个连接(作为qa),这一次将accepted=1作为on子句的一部分,然后我将COUNT(distinct qa.id)作为奖励(:)感谢您的帮助ctrahey:)第一个想法:将distinct添加到COUNT()子句中:
COUNT(distinct quotes.id)作为引用(
(目前,每个连接行都有一个连接,其中有四个连接,因此可能会有很多额外的行。DISTINCT应该将其缩减。抱歉,该注释似乎被截断了…抱歉,我在何处将DISTINCT添加到授予的
计数(NULLIF(q.accepted,0))
啊,得到了,在quotes表上进行了另一个连接(作为qa),这一次接受=1作为on子句的一部分,然后我将(不同的qa.id)计算为已授予的(:)感谢您的帮助ctrahey:)
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`