2013-04-01 32 views
2

我有一個數據集按:MySQL的MIN()函數返回只有一個記錄

+----+---------------+-------+-------------+---------------------+ 
| id | ip   | port | point_count | create_time   | 
+----+---------------+-------+-------------+---------------------+ 
| 1 | 192.168.20.28 | 10000 |   0 | 2013-03-29 14:29:14 | 
| 2 | 0.0.0.0  | 10000 |   0 | 2013-03-29 14:29:32 | 
| 3 | 0.0.0.1  | 11111 |   2 | 2013-03-29 14:29:38 | 
| 4 | 0.0.0.5  | 11112 |   3 | 2013-03-29 14:29:44 | 
+----+---------------+-------+-------------+---------------------+ 
4 rows in set (0.00 sec) 

現在,我使用MySQL的MIN()功能,按提取記錄:

mysql> SELECT s.id, s.ip, s.port, MIN(s.point_count) FROM origin_server s; 
+----+---------------+-------+--------------------+ 
| id | ip   | port | MIN(s.point_count) | 
+----+---------------+-------+--------------------+ 
| 1 | 192.168.20.28 | 10000 |     0 | 
+----+---------------+-------+--------------------+ 
1 row in set (0.00 sec) 

顯然,有兩列對於列point_count具有相同的值,但它只返回了一條記錄。我只想確認這種情況是否正確。感謝提前:)

+0

你在最小列想要什麼樣的價值?總分,還是每個IP /端口的最小值? – Bohemian

+0

我只希望只有一條記錄有最小的point_count :) –

回答

5

爲什麼你只得到一個記錄的原因是因爲MIN()是一個聚合函數返回一個記錄每一個組。由於您沒有指定GROUP BY子句,因此結果是正常的,只會給您一條記錄。

您可以使用子查詢來獲得point_count的最低值,並將其等同於外部查詢的point_count

SELECT * 
FROM origin_server 
WHERE point_count = (SELECT MIN(point_count) FROM origin_server) 

輸出

╔════╦═══════════════╦═══════╦═════════════╦═════════════════════╗ 
║ ID ║  IP  ║ PORT ║ POINT_COUNT ║  CREATE_TIME  ║ 
╠════╬═══════════════╬═══════╬═════════════╬═════════════════════╣ 
║ 1 ║ 192.168.20.28 ║ 10000 ║   0 ║ 2013-03-29 14:29:14 ║ 
║ 2 ║ 0.0.0.0  ║ 10000 ║   0 ║ 2013-03-29 14:29:32 ║ 
╚════╩═══════════════╩═══════╩═════════════╩═════════════════════╝ 
+1

+1你根據我對_why_和_how_提供的信息的請求編輯了你的問題,就像我輸入它的查詢一樣;-)那麼你能解釋一下mySql在不指定GROUP BY的情況下,選擇兩個(或多個)行中的哪一行作爲其「組」來返回?我認爲這只是基於聚集索引返回的第一行? – Sepster

+1

我瞭解到,非常感謝您的精彩答案:D –

+0

@Sepster您無法確定將被選中的記錄。它在手冊中有說明(*我正在尋找鏈接*)。 –

2

是,它是正確的,只有一條記錄被返回:返回的其他值是 「不明確」,不能可靠地視爲聚合的一部分!

如果使用聚合函數,則它將整個查詢有效地視爲單個組(禁止任何其他定義的分組)。要獲得定義良好行爲,然後在選擇列表中的所有列必須是聚集或必須在GROUP BY子句中被提及。

使用SELECT s.ip, MIN(s.point_count) FROM origin_server s GROUP by s.ip將返回4個記錄(與被施加每組MIN),因爲它定義了不同的分組。

使用SELECT MIN(s.point_count) FROM origin_server s將僅返回最小的point_count(在整個查詢中),這在邏輯上是正確的,並且是來自原始查詢的唯一保證的信息。以這種方式查看它時,只返回單個記錄是有意義的。

+0

+1。但是:「它可能會被其他值返回」。雖然在OP問題的背景下是這樣的,但這通常是否真實?例如,也許它可能是第一個找到的記錄,基於聚集索引?或者是_genuinely_未定義的行爲? – Sepster

+0

@Sepster在我的書中,它依賴於*確切的查詢計劃*和*這樣的*或者「不明確的」的實現。也就是說,對於給定的查詢[計劃]和數據庫,它可能是一致的 - 添加一個不同的索引,然後它可能完全是一個不同的查詢計劃。 – 2013-04-01 03:00:10

+0

啊,我明白了。是的,同意這是「不明確的」。我會把它稱爲「未定義的所有實際目的」。我來自MSSQL背景,其中聚合函數不能在包含非聚合結果的select中使用,除非每個非聚合列也明確包含在GROUP BY中。 – Sepster

0

MIN()函數是一個agregate功能。 所以這是正確的,如果你的代碼只返回1行的結果

+0

好的,謝謝你的回答:) –

1

很難知道你想要什麼,但試試這個:

select 
    ip, 
    port, 
    min(point_count) 
from origin_server 

這給你POINT_COUNT對的每個唯一組合的最小值IP和端口。

如果你想在IP和端口的最低POINT_COUNT,試試這個:

select 
    ip, 
    port, 
    point_count 
from origin_server 
order by 3 
limit 1 
+0

我只想只有一條記錄有最小的point_count :) –

+0

好的。請參閱編輯以回答希望更有用的內容。請注意,接受的答案可能會返回多行。 – Bohemian

+0

起初,我認爲如果我的問題的情況是不容許的,我會使用LIMIT,謝謝你的回答:) –