2012-11-19 47 views
13

表:PHP的MySQL集團通過獲得最新的記錄,而不是第一個記錄

(`post_id`, `forum_id`, `topic_id`, `post_time`) 
(79, 8, 4, '2012-11-19 06:58:08'); 
(80, 3, 3, '2012-11-19 06:58:42'), 
(81, 9, 9, '2012-11-19 06:59:04'), 
(82, 11, 6, '2012-11-19 16:05:39'), 
(83, 9, 9, '2012-11-19 16:07:46'), 
(84, 9, 11, '2012-11-19 16:09:33'), 

查詢:

SELECT post_id, forum_id, topic_id FROM posts 
GROUP BY topic_id 
ORDER BY post_time DESC 
LIMIT 5 

結果:

[0] => [post_id] => 84 [forum_id] => 9 [topic_id] => 11 
[1] => [post_id] => 82 [forum_id] => 11 [topic_id] => 6 
[2] => [post_id] => 81 [forum_id] => 9 [topic_id] => 9 
[3] => [post_id] => 80 [forum_id] => 3 [topic_id] => 3 
[4] => [post_id] => 79 [forum_id] => 8 [topic_id] => 4 

問題:

如何重寫查詢,以便我t返回post_id - > 83而不是post_id - > 81?

它們都具有相同的論壇和主題ID,但POST_ID - > 81比POST_ID的舊日期 - > 83.

但似乎集團通過獲得的「第一」的記錄,而不是「最新'一個。

我試圖改變查詢

SELECT post_id, forum_id, topic_id, MAX(post_time) 

但同時返回POST_ID 81和83

回答

24

如果您選擇了未在組合子句中使用且不是聚合的屬性,則結果未指定。 I.e您不知道哪些行選擇了其他屬性。 (sql標準不允許這樣的查詢,但MySQL更輕鬆)。

然後查詢應該寫成例如作爲

SELECT post_id, forum_id, topic_id 
FROM posts p 
WHERE post_time = 
    (SELECT max(post_time) FROM posts p2 
    WHERE p2.topic_id = p.topic_id 
    AND p2.forum_id = p.forum_id) 
GROUP BY forum_id, topic_id, post_id 
ORDER BY post_time DESC 
LIMIT 5; 

SELECT post_id, forum_id, topic_id FROM posts 
NATURAL JOIN 
(SELECT forum_id, topic_id, max(post_time) AS post_time 
FROM posts 
GROUP BY forum_id, topic_id) p 
ORDER BY post_time 
LIMIT 5; 
+0

感謝您的解釋和代碼。兩個查詢都有效。 – shanebp

+0

我用過你第​​一個查詢,但它在我改變 ...之前沒有工作... WHERE post_time = ... TO ... WHERE post_time IN ...因爲我得到了更多的結果。 –

+0

這是爲什麼這麼麻煩?使用SQL它將只是'選擇*從[表] GROUP BY [列]'選擇最新的,而不是最古老的,似乎合乎邏輯的權利? –

10

這不是很漂亮,但它的工作原理:

SELECT * FROM (SELECT post_id, forum_id, topic_id FROM posts 
ORDER BY post_time DESC) as temp 
GROUP BY topic_id 
+0

這消除重複,但結果是主題ID ASC – shanebp

+2

添加這對您的查詢的順序進行它的工作:ORDER BY post_time DESC LIMIT 5 – shanebp

5

嘗試類似

SELECT post_id, forum_id, topic_id 
FROM (SELECT post_id, forum_id, topic_id 
     FROM posts 
     ORDER BY post_time DESC) 
GROUP BY topic_id 
ORDER BY topic_id desc 
LIMIT 0,5 

根據需要更改order bylimit

+0

結果是一個空數組。 – shanebp

+0

我稍微編輯了查詢。我不明白爲什麼它不起作用。我沒有嘗試過,但這是一種常用技術。嵌套查詢是。假設內部查詢返回正確的結果,那麼外部查詢應該給出結果。 – NappingRabbit

+0

如果你想調試,首先運行內部查詢。 – NappingRabbit

0

也許不是這樣做的最佳方式,但有時功能GROUP_CONCAT()可以userfull,它將返回排序像你想對所有的字符串值並用逗號分隔(耦合值由空格分隔)。然後我使用函數SPLIT_STRING()來剪切字符串中的第一個id。

SELECT 
post_id, 
SPLIT_STRING(group_concat(forum_id, post_time ORDER BY post_time DESC) ,' ',1)as forum_id, 
SPLIT_STRING(group_concat(topic_id, post_time ORDER BY post_time DESC) ,' ',1)as topic_id , 
FROM posts 
GROUP BY topic_id 
ORDER BY post_time DESC 
LIMIT 5 

所以聚集forum_id,post_time會是這樣:

81 2012年11月19日06:59:04,83 2012年11月19日16時07分46秒

因此,你需要用整數和日期時間夫婦的字符串表示工作,用逗號分隔每個新人,所以我用這個函數來獲取第一INT:

CREATE FUNCTION SPLIT_STRING(str VARCHAR(255), delim VARCHAR(12), pos INT) 
RETURNS VARCHAR(255) 
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, pos), 
     LENGTH(SUBSTRING_INDEX(str, delim, pos-1)) + 1), 
     delim, ''); 

注:功能SPLIT_STRING(STR,DELIM,POS)發現這裏:Equivalent of explode() to work with strings in MySQL

0

這也將正常工作適合你。

SELECT * 
FROM (
    SELECT post_id, forum_id, topic_id FROM posts 
    ORDER BY post_time DESC 
    LIMIT 5 
) customeTable 
GROUP BY topic_id 
相關問題