2013-08-20 70 views
0

我一直在尋找一種方法來適應找到最大和最小的多個結果。我發現這個鏈接上一個問題: max Countsmysql max有多個實例

答案之一是給出:

SELECT color_id, COUNT(color_id) totalCount 
FROM products 
WHERE item_id = 1234 
GROUP BY color_id 
HAVING COUNT(color_id) = 
(
    SELECT COUNT(color_id) totalCount 
    FROM products 
    WHERE item_id = 1234 
    GROUP BY color_id 
    ORDER BY totalCount DESC 
    LIMIT 1 
) 

這是公認的做法尤其是對於大型數據庫?如果這有意義,上述查詢是否基本上在本身內部運行?

我有一個更復雜的查詢也需要找到馬和最小。我想優化它:

編輯

SELECT `system_users`.`first`, `system_users`.`last`, COUNT(`quotes`.`created_by`) as most_quotes 
FROM `quotes` 
INNER JOIN `system_users` 
ON `quotes`.`created_by` = `system_users`.`id` 
where `system_users`.`store_id` = '$createdID' 
and `quotes`.`date_created` between '$startDate' and '$endDate' group by(`created_by`) 
HAVING count(`quotes`.`created_by`) = 
(
SELECT COUNT(`quotes`.`created_by`) 
FROM `quotes` 
INNER JOIN `system_users` 
ON `quotes`.`created_by` = `system_users`.`id` 
where `system_users`.`store_id` = '$createdID' 
and `quotes`.`date_created` between '$startDate' and '$endDate' group by(`created_by`) ORDER BY count(`created_by`) DESC limit 1 
) 
OR 
(
SELECT COUNT(`quotes`.`created_by`) 
FROM `quotes` 
INNER JOIN `system_users` 
ON `quotes`.`created_by` = `system_users`.`id` 
where `system_users`.`store_id` = '$createdID' 
and `quotes`.`date_created` between '$startDate' and '$endDate' group by(`created_by`) ORDER BY count(`created_by`) ASC limit 1 
) 
ORDER BY most_quotes ASC 

我試圖想不同的方式來找到max和沒有運氣閔至今。任何更多的幫助,將不勝感激 謝謝 mc

+0

任何幫助嗎? – mrcurious

回答

1

這是一個壞主意 - 在大型數據庫上使用HAVING。而且,除此之外,你的問題就可以解決這樣(我的MySQL 5.5版本):

SELECT 
    color_id, 
    COUNT(color_id) AS totalCount 
FROM  
    products 
WHERE 
    item_id = 1234 
GROUP BY 
    color_id 
ORDER BY 
    totalCount DESC 
LIMIT 1 

HAVING的問題是,整個查詢已完成後執行,即存儲引擎已經工作過,所以沒有索引或其他優化可以爲HAVING條件完成 - 因此,它可以被視爲完整的結果集掃描。

感謝@GordonLinoff我發現它不完全是你想要的東西。如果你想找到所有相應的行,你最好像戈登建議的那樣行事。

雖然我已經找到了另一種方式來解決這個問題,它可能只比原變種一對夫婦更好地HAVING(和 - 更好,因爲存儲引擎將參與兩次)

SELECT 
    first.color_id, 
    first.rows_count 
FROM 
    (SELECT color_id, COUNT(1) AS rows_count FROM products WHERE item_id=1234 GROUP BY color_id) AS first 
    LEFT JOIN 
    (SELECT color_id, COUNT(1) AS rows_count FROM products WHERE item_id=1234 GROUP BY color_id ORDER BY rows_count DESC LIMIT 1) AS second 
    ON first.rows_count=second.rows_count 
WHERE second.rows_count IS NOT NULL; 

我已經也得到變量(類似於Gordon的變量)。所以你可以選擇這些選項。

+0

這可能是一個更高效的查詢,但它不回答問題。這個問題明確指出,不止一個「color_id」可以滿足最大條件。這隻返回一個值。 –

+0

嗯.. @GordonLinoff,你是正確的 - 因爲上面的查詢將只返回一行。我會糾正的。 –

+0

感謝您的回覆。儘管我的查詢比這更復雜一點。現在,這是我有什麼,找到一個最大值和最小值: – mrcurious

0

你的問題的答案是有多種方法可以在MySQL中使用一個查詢來處理這個問題。

一種方法是在你的問題中的方法。另一個辦法是使用變量:

select color_id, totalcount 
from (SELECT color_id, COUNT(color_id) as totalCount, 
      @maxcount = if(@maxcount < count(color_id), count(color_id), @maxcount) 
     FROM products cross join 
      (select @maxcount := 0) const 
    WHERE item_id = 1234 
    GROUP BY color_id 
    ) t 
where totalCount = @maxcount; 

我不能在MySQL中使用變量的忠實粉絲,但他們往往是有效表達查詢的唯一途徑。我相信這是最有效的方式來編寫你想要的單一查詢。

第三種方法是使用臨時表。第四種方法是將having條件中的子查詢移動到另一個連接。

在大多數其他數據庫中,您只需使用窗口函數。例如:

select color_id, totalcount 
from (SELECT color_id, COUNT(color_id) as totalCount, 
      max(count(color_id)) over() as maxTotalCount 
     FROM products 
    WHERE item_id = 1234 
    GROUP BY color_id 
    ) t 
where totalCount = maxTotalCount; 

但是,MySQL不支持這些。

編輯:

如果你想最大和使用變量最小:

select color_id, totalcount 
from (SELECT color_id, COUNT(color_id) as totalCount, 
      @maxcount = if(@maxcount < count(color_id), count(color_id), @maxcount), 
      @mincount = if(@mincount > count(color_id) or @mincount = -1, count(color_id), @mincount) 
     FROM products cross join 
      (select @maxcount := -1, @mincount := -1) const 
    WHERE item_id = 1234 
    GROUP BY color_id 
    ) t 
where totalCount in (@mincount, @maxcount); 
+0

你能提出一個解決上面我編輯的查詢嗎?謝謝 – mrcurious

+0

我跑這個查詢,它返回空列 – mrcurious