1

次のようなクエリがあります。

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;

1 つのクエリを実行して、すべての引用符の数を取得します

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

次に、各商人をループし、配列から各商人のカウントを引き出します。

mysql はどれくらい速いですか? 2 番目の方法は大きな利益をもたらすでしょうか、それともどちらの方法も受け入れられるでしょうか?

一般的な参考のために、私の実際のクエリは次のとおりです。

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 からの回答を使用して、クエリを変更しました。

したがって、現在、クエリの 3 つのバージョンがあります。

ctrahys:

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`

それらはすべてほぼ同じ結果を返しますが、最後の 4 つのフィールドに違いがあります (したがって、ここでは結果配列から他のすべての行を削除しています)。

元のクエリから (正しい結果):

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'),
4

1 に答える 1

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

このクエリはまさにあなたが必要としているものであり、非常に高速です!

実際のクエリを編集する

(IIRC) COUNT()false/0 をカウントしますが、NULL はカウントしないため、実際のクエリで必要な唯一の警告は、受け入れられた引用符のカウント内の NULLIF ビットです。

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`
于 2012-08-27T04:55:18.943 に答える