2015-11-01 11 views
1

我的目標是從每個帳戶的表格中獲取最後幾行(我正在嘗試三行)。我沒有問題得到第一排,但我無法制作前三排最近的排。舉例來說,假設我有如下表:如何抓取MySQL中的最後三行

+--------+------------+------------+-----------+ 
| rownum | entryDate | particular | accountID | 
+--------+------------+------------+-----------+ 
|  1 | 2015-10-01 | Item1  |   1 | 
|  2 | 2015-10-01 | Item2  |   1 | 
|  3 | 2015-10-02 | Item3  |   1 | 
|  4 | 2015-10-02 | Item4  |   1 | 
|  5 | 2015-10-02 | Item5  |   2 | 
|  6 | 2015-10-03 | Item6  |   2 | 
|  7 | 2015-10-05 | Item7  |   3 | 
+--------+------------+------------+-----------+ 

我想要得到的是:

+--------+------------+------------+-----------+ 
| rownum | entryDate | particular | accountID | 
+--------+------------+------------+-----------+ 
|  4 | 2015-10-02 | Item4  |   1 | 
|  3 | 2015-10-02 | Item3  |   1 | 
|  2 | 2015-10-01 | Item2  |   1 | 
|  6 | 2015-10-03 | Item6  |   2 | 
|  5 | 2015-10-02 | Item5  |   2 | 
|  7 | 2015-10-05 | Item7  |   3 | 
+--------+------------+------------+-----------+ 

Item1移除,因爲它已經收到了3。 我試着下面的代碼,但它並沒有檢索最近

select rownum, entryDate, particular, accountID 
from (
    select entryDate, particular, accountID 
    @rownum := if(@account = accountID, @rownum + 1, 1) rownum, 
    @account := accountID 
    from entries 
    join (select @rownum := 0, @account := 0) init 
    order by accountID, entryDate desc) t 
where t.rownum <= 3 -- Limits the rows per account 

如果任何人都可以在那簡直太好了正確的方向指向我!

編輯: 然而,正是我作爲檢索的結果是:

+--------+------------+------------+-----------+ 
| rownum | entryDate | particular | accountID | 
+--------+------------+------------+-----------+ 
|  3 | 2015-10-02 | Item3  |   1 | 
|  2 | 2015-10-01 | Item2  |   1 | 
|  1 | 2015-10-01 | Item1  |   1 | 
|  6 | 2015-10-03 | Item6  |   2 | 
|  5 | 2015-10-02 | Item5  |   2 | 
|  7 | 2015-10-05 | Item7  |   3 | 
+--------+------------+------------+-----------+ 

另外,如果有幫助,我對MySQL的工作臺,SQLbuddy,PHP(Web應用程序測試此)和PHPMyAdmin,他們都產生相同的結果

+0

爲什麼會出現子選擇查詢?它的目的是什麼? –

+0

哪個子查詢?如果您指的是'from'內的那個,那麼每個帳戶的行數可以限制爲3個。連接內的子查詢用於初始化變量。 – Jujunol

+1

您的查詢實際上給出了您列出的結果 - 問題是什麼? – amdixon

回答

1

Your query works for me如果我修復語法錯誤。

select rownum, entryDate, particular, accountID 
from (
    select entryDate, particular, accountID, 
    @rownum := if(@account = accountID, @rownum + 1, 1) rownum, 
    @account := accountID 
    from entries 
    join (select @rownum := 0, @account := 0) init 
    ORDER BY accountid, entryDate desc 
) t 
where t.rownum <= 3; 

rownum entryDate   particular   accountID 
1  October, 02 2015  Item3    1 
2  October, 02 2015  Item4    1 
3  October, 01 2015  Item1    1 
1  October, 03 2015  Item6    2 
2  October, 02 2015  Item5    2 
1  October, 05 2015  Item7    3 

請注意,Item1和Item2具有相同的entryDate。無法預測您是否會獲得Item1,3和4或2,3和4.但是,您永遠不應該獲得Item1,2和3.

另請注意,rownum不是1到7,而是分別遞增每個帳戶。這是對的。對於相同的查詢,您的輸出不同。我想我知道發生了什麼事。

你很聰明的子查詢依賴於子選擇中列的操作順序。特別是這個。

@rownum := if(@account = accountID, @rownum + 1, 1) rownum, 
    @account := accountID 

這就是爲每個帳戶分配一組單獨的rownums的技巧。它依靠這樣的事實,即行按帳戶排序,@rownum@account之前設置。

問題是,我不認爲你可以依靠那個。

+0

這個輸出與他需要的不同#Item1'不應該在那裏而是'item2'應該在那裏..對嗎? –

+0

對,我忽略了Item1和2在測試數據中有相同的日期。當項目2日期切換到* -02在SQLFiddle提供之前我甚至注意到了,結果工作意味着它與我的服務器做我猜:/ – Jujunol

+0

@Jujunol我懷疑問題是作戰中選擇列的順序是不可靠的。我不完全確定。 – Schwern

2

寫這個查詢一個安全的方式是:

select rownum, entryDate, particular, accountID 
from (select entryDate, particular, accountID, 
      (@rownum := if(@account = accountID, @rownum + 1, 
          if(@account := accountID, 1, 1) 
          ) 
      ) as rownum, 
     from entries cross join 
      (select @rownum := 0, @account := 0) init 
     order by accountid, entryDate desc 
    ) t 
where t.rownum <= 3; 

這在documentation解釋說:

比SET語句作爲一般規則,其他的,你永遠不應該 分配值賦給用戶變量並讀取同一個 語句中的值。 。 。在下面的語句,你可能會認爲,MySQL的 將評估@a第一,然後做一個分配第二:

SELECT @a, @a:[email protected]+1, ...; 

但是,評價涉及用戶 變量表達式的順序是不確定的。

相關問題