2013-02-27 121 views
1

任何人都可以解釋爲什麼以下語句在MySQL中工作但在Oracle中收到「不是GROUP BY表達式」的原因嗎?Oracle vs MySQL - 聚合函數

SELECT order1.user_id, 
     order1.order_datetime, 
     SUM(order2.order_total) 
    FROM order_table order1 
    JOIN order_table order2 ON order1.user_id = order2.user_id 
GROUP BY order1.user_id 

這是因爲Oracle不知道如何處理order_datetime列?難道不能像它在MySQL中那樣從GROUP BY order1.user_id行收到的行中返回列結果嗎?

編輯:

據我所知,所有列應在group by,但我試圖理解爲什麼Oracle沒有返回類似的結果作爲MySQL的(而MySQL不要求每個GROUP BY和Oracle)。

+2

因爲MySQL不喜歡小貓。 – Kermit 2013-02-27 18:22:28

+4

因爲MySQL認爲只需選擇任意'order1.order_datetime'即可。在其他嚴重的數據庫平臺中,won syntax語法是不合法的。僅僅因爲MySQL對語法的鬆懈並不能使它正確。 – 2013-02-27 18:25:41

回答

12

Oracle實際上執行的是正確的行爲。當您使用GROUP BY時,選擇列表中的項目必須出現在GROUP BY或集合函數中。

SELECT order1.user_id, 
     order1.order_datetime, 
     SUM(order2.order_total) 
    FROM order_table order1 
    JOIN order_table order2 ON order1.user_id = order2.user_id 
GROUP BY order1.user_id, order1.order_datetime 

MySQL使用一個EXTENSION TO GROUP BY允許不執行該FULL GROUP BY的行爲。在MySQL中使用它並不能保證order1.order_datetime的值是什麼,MySQL只選擇一個值,結果可能是意外的。

您需要使用GROUP BY或在SELECT列表中的所有項目上進行彙總(與上面類似),或者您必須重新編寫查詢。您可以使用任何如下:

SELECT order1.user_id, 
     min(order1.order_datetime) order_datetime, 
     SUM(order2.order_total) 
    FROM order_table order1 
    JOIN order_table order2 ON order1.user_id = order2.user_id 
GROUP BY order1.user_id 

,一個總量適用於order_datetime,那麼你不通過之日起必須組。

您可以使用sum() over()

SELECT order1.user_id, 
     order1.order_datetime, 
     SUM(order2.order_total) over(partition by order1.user_id) order_total 
FROM order_table order1 
JOIN order_table order2 ON order1.user_id = order2.user_id 

或者這可以使用子查詢重寫。

SELECT order1.user_id, 
    order1.order_datetime, 
    order2.order_total 
FROM order_table order1 
JOIN 
(
    select SUM(order_total) order_total, user_id 
    from order_table 
    group by user_id 
) order2 
    ON order1.user_id = order2.user_id 
+0

bluefeet - 感謝您的詳細回覆。是否仍然可以使用group by來僅檢索每個用戶1條記錄,order_total來自order2? – Mike 2013-02-27 18:19:08

+0

@Mike我提供的最終查詢爲您提供了每個用戶的總訂單。如果您不想使用子查詢,並且您不想使用「按order_datetime」進行分組,則可以在該列周圍使用聚合函數。 – Taryn 2013-02-27 18:22:55

+6

@Mike,您可以使用聚合函數,例如MIN(order1.order_datetime)來指示您需要第一個日期時間。不幸的是,詢問項目組並不指定確定如何選擇組屬性的聚合是不正確的。如果你有一羣男人和女人,那麼詢問男人的年齡和女人羣的年齡是不正確的,你可能需要平均值,最小值或者最大值或者總值,但該組的「年齡」是毫無意義的。 – 2013-02-27 18:23:45

0

在oracle中則需要指定Select所有列在group by,如果你想組由只有一列,而不是所有的嘗試這個

SELECT order1.user_id, 
     order1.order_datetime, 
SUM(order2.order_total) OVER (PARTITION BY order1.user_id) order_total 
    FROM order_table order1 
    JOIN order_table order2 ON order1.user_id = order2.user_id 
0

見我相關的問題here
的Mysql假定「非任何」值爲非分組功能/字段,而Oracle強制需要分組功能或分組按字段

Mysql manual
MySQL extends the use of GROUP BY so that the select list can refer to nonaggregated columns not named in the GROUP BY clause. This means that the preceding query is legal in MySQL. You can use this feature to get better performance by avoiding unnecessary column sorting and grouping. However, this is useful primarily when all values in each nonaggregated column not named in the GROUP BY are the same for each group. The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause. Sorting of the result set occurs after values have been chosen, and ORDER BY does not affect which values the server chooses.

+2

我不明白這是如何相關的......或者真的回答了這個問題。 – Kermit 2013-02-27 18:30:11