2010-03-30 325 views
4

所以我不認爲自己是在MySQL的新手,但是這其中有我難住了:欺騙性MySQL查詢

我有一個留言板,我想通過拉線程分組所有最近發表的文章列表ID。

這裏的表:

MB_Posts 
-ID 
-Thread_ID 
-Created_On (timestamp) 
-Creator_User (user_id) 
-Subject 
-Contents 
-Edited (timestamp) 
-Reported 

我已經嘗試了很多不同的東西,以保持它的簡單,但我想從這個社會的幫助。

只是踢了這一點那裏...如預期這一個不工作:

SELECT * FROM MB_Posts GROUP BY Thread_ID ORDER BY ID DESC 

期望的結果:

一組最近發表的文章,每一個線程ID

+1

你預計會發生什麼,實際發生了什麼? – 2010-03-30 18:27:15

+1

你能否澄清你期望的結果?我不確定你在這方面「分組」的含義 - 你想回來什麼? – 2010-03-30 18:27:25

+0

什麼錯誤消息或結果,當你運行它時,你會得到什麼?或者它只是沒有做任何事情(返回0行)? 我認爲Thread_ID是帖子所屬的線程(會話)? – jefflunt 2010-03-30 18:31:42

回答

3

GROUP BY重寫ORDER BY(沒有例外)。

SELECT * 
FROM MB_Posts 
WHERE ID IN (SELECT MAX(ID) FROM MB_Posts GROUP BY Thread_ID) 

應該給你你需要的東西。

詳細瞭解hidden columns in group by(原始查詢中的所有列,除了THREAD_ID被隱藏)

+0

該死的!這工作!謝謝你不合理。 – jerebear 2010-04-02 04:11:41

0

當您使用GROUP BY時,您必須在語句的SELECT部分中具有聚合函數。

+0

我已經能夠用戶GROUP BY並返回我需要的結果,但請解釋我將如何在SELECT部分​​實現一個聚合函數並返回所需的結果組。 – jerebear 2010-03-30 18:58:36

0

好的,我有一個建議。讓我知道:

SELECT 
    MB_Posts.*, 
    (SELECT 
     GROUP_CONCAT(CreatedOn ORDER BY CreatedOn DESC) 
     FROM MB_Posts AS P 
     WHERE P.Thread_ID = MB_Posts.Thread_ID) 
    AS `sort` 
FROM MB_Posts 
ORDER BY `sort` DESC, CreatedOn DESC 
+0

這就是如果我想從單個線程中選擇單個最近的帖子。這是涵蓋。我想要的是每個線程最近發佈的帖子,作爲單個查詢的結果。 – jerebear 2010-03-30 19:02:29

+0

不用擔心。感謝您的反饋。 – jerebear 2010-03-30 19:05:19

+0

我認爲我用更好的東西編輯了我的答案。 – Jage 2010-03-30 19:24:51

0

這裏是另一種方式:

SELECT * FROM mb_posts ORDER BY ID DESC 

threadsHistory = array(); 
while (row) 
{ 
    if (row) NOT IN threadsHistory 
    { 
     add values to array (for example thread_ID and postID) 
     count++; 
    } 
    if count == 10 break; 
} 

這不正是一個很好的和乾淨的方式,但它應該有一點點扭曲

+0

試過了。嘗試了很多事情......在實際的語法上遇到困難。我試過JOINS,Nexted Queries和各種聚合器。這只是一個棘手的問題。 – jerebear 2010-03-30 18:59:08

+0

事實上,我只是試圖在我的一個數據庫中找到解決方案,但沒有成功。如果你不介意的話,你總是可以使用簡單的代碼循環。 – mspir 2010-03-30 19:20:43

+0

我編輯了答案,這是一種可以肯定的方式,但它不是我猜的最好最乾淨的方式。 – mspir 2010-03-30 19:52:29

0

GROUP BY希望重返工作每個獨特的組一行,例如

SELECT COUNT(*) FROM mb_post GROUP BY thread_id; 

將返回每個線程中的帖子數量。

您需要通過thread_id,id執行一個命令,然後以編程方式處理所需的「分組」,例如,

for (row in rows) { 
    print("<tr><th>"); 
    if (row["thread_id"] != prev_id) { 
     print(thread_id) 
     prev_id = thread_id; 
    } 
    print("</th>") 
+0

我明白了。但GROUP BY將根據組返回元素的FIRST實例,並在最後忽略ORDER BY語句。這種方法似乎最簡單,但不起作用。 – jerebear 2010-03-30 19:00:18

+0

是的,這就是爲什麼你需要改變SELECT查詢。 SELECT * FROM mb_post ORDER BY Created_On DESC 將選擇按創建日期排序的所有帖子按desc順序排列,然後您可以應用上述代碼。 – mspir 2010-03-30 19:32:11

+0

該死的......不,它不會工作......你還需要更改已顯示線程的檢查。也許在每次遇到新數組時都要向數組中添加一個值,並且當數組達到X的大小時,可以停止循環。 – mspir 2010-03-30 19:38:21

0

給這個旋轉,看看它是否適合你想要的。這應該會顯示最近的100條帖子,並且結果將按照它們所屬的帖子進行排序。

SELECT MB_Posts.* 
    FROM MB_Posts 
    INNER JOIN (
    SELECT ID FROM MB_Posts ORDER BY Created_On DESC LIMIT 0, 100 
) as MostRecentPosts ON MB_Posts.ID = MostRecentPosts.ID 
    ORDER BY Thread_ID, Created_On DESC; 

根據您的修改「一組最近發表的文章,每個線程ID一個」,從子查詢創建表可以使用小CONCAT和比較神奇的創建。這將取決於你的列類型是什麼,但應該爲大多數工作。這兩種解決方案的想法都是使用子查詢來處理聚合過程,並確定所需記錄的ID,然後根據該子查詢的結果連接表以檢索行的其餘數據。

SELECT MB_Posts.* 
    FROM MB_Posts 
    INNER JOIN (
    SELECT TRIM(LEADING '0' FROM 
     SUBSTRING(MAX(CONCAT(UNIX_TIMESTAMP(Created_On), LPAD(ID,15,'0'))), -15)) AS ID 
    FROM MB_Posts 
    GROUP BY Thread_ID 
) as MostRecentPostPerThread ON MB_Posts.ID = MostRecentPostPerThread.ID 
    ORDER BY Thread_ID, Created_On DESC; 
+0

試過了。它將返回表格中的每個帖子。 :( – jerebear 2010-03-30 19:01:25

+0

你使用的是什麼版本的mysql?也許我剛剛在本地重新測試過,以驗證它是否正確返回最近的100個條目。 – 2010-03-30 19:04:22

+0

根據您的修改要求,您是否在第一個答案中刪除了0,100的限制?那肯定會讓你回到每一個帖子。我已經根據修改後的要求添加了一個解決方案,允許按一個字段進行分組,然後按另一個字段進行排序,然後通過將該ID支持到排序字段,然後在組排序後將其剝離, )操作。 – 2010-03-30 19:48:46

0

嗯......不Created_On或編輯的決定「最近?」

假設Created_On是什麼想:

選擇的thread_id,MAX(Cre​​ated_On)FROM MB_Posts GROUP BY的thread_id;

給出了每個Thread_ID的最新時間戳。這些半連接到MB_Posts 喜歡的東西

SELECT * FROM MB_Posts JOIN(選擇的thread_id,MAX(Cre​​ated_On)AS Created_On FROM MB_Posts GROUP BY的thread_id)最新 使用(THREAD_ID,Created_On);

+0

這一個也工作!謝謝JayDee – jerebear 2010-04-02 04:18:01