2012-06-27 37 views
4

在我的應用程序中,每個產品組都有很多產品,每個產品都有一個製造商。這些關係由MySQL存儲在InnoDB表product_groups中,其中id字段和productsid,product_groupmanufacturer字段。在MySQL中沒有子查詢字段的模式計算?

有沒有辦法找到每個產品組中最常見的製造商,而不訴諸於選擇子查詢?

這是如何我目前做:

SELECT product_groups.id, 
    (
    SELECT manufacturer FROM products 
    WHERE product_group = product_groups.id 
    GROUP BY manufacturer 
    ORDER BY count(*) DESC 
    LIMIT 1 
) manufacturer_mode 
FROM product_groups; 

回答

5

嘗試這種解決方案:

SELECT 
    a.product_group, 
    SUBSTRING_INDEX(GROUP_CONCAT(a.manufacturer ORDER BY a.occurrences DESC SEPARATOR ':::'), ':::', 1) AS manufacturer_mode 
FROM 
    (
     SELECT 
      aa.product_group, 
      aa.manufacturer, 
      COUNT(*) AS occurrences 
     FROM 
      products aa 
     GROUP BY 
      aa.product_group, 
      aa.manufacturer 
    ) a 
GROUP BY 
    a.product_group 

說明:

這仍然使用子查詢的一種形式,但其中一個執行只有一次,而不是像在原始示例中那樣逐行執行一次。

它通過首先選擇product_group id,製造商以及製造商爲每個特定組顯示的次數來工作。

FROM子選擇會看起來像這樣執行後(只是做了數據在這裏):

product_group | manufacturer | occurrences 
--------------------------------------------------- 
1    | XYZ   | 4 
1    | Test   | 2 
1    | Singleton  | 1 
2    | Eloran   | 2 
2    | XYZ   | 1 

現在,我們有子選擇的結果,我們需要挑選出具有行每個產品組的occurences字段中的最大值。

在外部查詢,我們組子選擇再次受到product_group場,但這一次,只有product_group領域。現在,當我們在這裏執行我們的GROUP BY時,我們可以在MySQL中使用一個非常引人注目的函數,稱爲GROUP_CONCAT,我們可以使用這個函數將製造商以任意順序連接在一起。

...GROUP_CONCAT(a.manufacturer ORDER BY a.occurrences DESC SEPARATOR ':::'... 

我們這裏做的是串聯的廠商一起被每product_group ID組合在一起時,ORDER BY a.occurrences DESC可以確保與出場次數最多的生產廠家出現第一在拼接列表。最後,我們將每個製造商與:::分開。本作product_group1結果將類似於:

XYZ:::Test:::Singleton 

XYZ首先出現,因爲它在occurance領域的最高值。我們只有想要選擇XYZ,所以我們包含在SUBSTRING_INDEX之內的連接,這將允許我們僅基於:::定界符選擇列表的第一個元素。

最終的結果將是:

product_group | manufacturer_mode 
--------------------------------------- 
1    | XYZ 
2    | Eloran 
+0

的'SUBSTRING_INDEX(GROUP_CONCAT('實在是太醜了,但我真的很喜歡的方式它被用來回答這個問題。+1:p –

+0

順便說一下,在這裏不處理同一產品的同等事件的情況不是嗎? –

+1

@OlivierCoilland,這個問題沒有說明應該如何處理同等事件。現在如果有的話,它會選擇第一個出現。也許OP想要根據一個額外的字段對它進行排序,這隻需要在GROUP_CONCAT()的ORDER BY中添加另一個字段。 –