2016-04-14 105 views
1

我試圖從select中的每個組中獲取最近一行,但有一點扭曲。MySQL從兩列中選擇組中的最後一行

獲取例如下表:

id , user_id , created_at   , balance 
1 , 1  , 2016-01-01 01:01:01 , 1  
2 , 1  , 2016-01-01 01:01:01 , 2  

你可以看到created_at值是相同的用戶是相同的,而問題是,我不能靠id字段既不是因爲沒有保證最大的id將是最後一個。

如果created_at字段將不可複製下面的查詢將正常工作:

SELECT L.id 
    , L.user_id 
    , L.created_at 
    , L.balance 
FROM log AS L 
     JOIN 
     (SELECT user_id 
       , MAX(created_at) AS max_created_at 
      FROM log 
      GROUP BY user_id) MAX_TIME ON L.user_id = MAX_TIME.user_id 
            AND L.created_at = MAX_TIME.max_created_at; 

但由於重複created_at的,它將返回兩行。 所以我不能只依賴created_at字段,但我相信,如果created_at是重複的話,獲取最大ID會給我我想要的結果。

所以我需要添加id行以及以某種方式這個「組」機制。 任何想法如何做到這一點?

回答

0

如果您選擇哪一行真的不重要,您可以通過唯一的行ID進行排序,並且只選擇頂部1.如果您想要最後一行行,即具有最大唯一ID的行,你會想ORDER BY ... DESC

SELECT TOP 1 
     L.id 
    , L.user_id 
    , L.created_at 
    , L.balance 
FROM log AS L 
     JOIN 
     (SELECT user_id 
       , MAX(created_at) AS max_created_at 
      FROM log 
      GROUP BY user_id) MAX_TIME ON L.user_id = MAX_TIME.user_id 
            AND L.created_at = MAX_TIME.max_created_at; 
            ORDER BY L.id DESC 
+0

他說: >問題是我不能依靠id字段,因爲沒有保證最大的id將是最後一個。 ... – Vincent

+0

我仍然通過created_at最大化。我只是通過使用ORDER BY忽略了一個單一的ID來縮小重複的結果。 – LCIII

+0

這個查詢的問題是它將完全返回一行。什麼是需要返回每個用戶的最新行。 – emul

0

如果你與你的ID創建的表作爲AUTO_INCREMENT(我強烈推薦這種方式),最大的一個應該是最新的行...

所以:

SELECT L.id 
    , L.user_id 
    , L.created_at 
    , L.balance 
FROM log AS L 
     JOIN 
     (SELECT user_id 
       , MAX(id) AS last 
      FROM log 
      GROUP BY user_id) MAX_TIME ON L.user_id = MAX_TIME.user_id 
            AND L.id = MAX_TIME.last; 

(只是id

更換created_at但是,如果你沒有「正常」的ID,我覺得沒有辦法做到這一點......

+0

問題是因爲我寫的是我不能依賴auto_increment字段。原因是這是一個日誌表,並且條目不一定按順序排列。 – emul

+0

@emul好的,但在這種情況下,你不能「真正」選擇最新的(是的,它的工作原理基於日期,但日期是相同的?)...爲此,你需要一個絕對標識符,你可以依賴一個註冊順序...所以我沒有其他建議,只能創建第二個'id'字段,由'auto_increment'填充......否則您的數據庫系統將不會記錄輸入順序...(對於MySQL,也許在information_schema中,但我不確定,並且它不是檢索數據的好方法...)。或者你可以說,這種情況(相同的創建時間!)是例外,並且不會發生在生產中...... – Vincent

0

爲什麼你真正需要的是自聯接?

豈不

SELECT L.id 
, L.user_id 
, L.created_at 
, L.balance 
FROM log AS L 
GROUP BY L.user_id 
ORDER BY L.created_at DESC, L.id DESC; 

得到你所期望的行?

說明:排序首先發生,這樣最近的日期時間已經在第一行。由於重複日期時間值的可能性,我們通過id添加另一個排序。現在,具有最新日期時間和最高ID的行將位於第一行,然後結果按用戶ID分組。

+0

這不會拋出錯誤,因爲所有非user_id字段也需要彙總? – LCIII

+0

不,爲什麼應該他們被聚合?非分組字段上的聚合只發生在組函數中,例如SUM(),AVG(),... – Paul

+0

我不確定你期望這個查詢會返回什麼。如果你正在使用group通過聲明或集合以某種方式列出組中的字段。 – emul