2011-11-26 79 views
2

試想一個MySQL表是這樣的:找出一組項目的最後一個項目在SQL

--------------------------- 
ListID | itemID | Item 
--------------------------- 
List_1 | item_1 | Apple 
--------------------------- 
List_1 | item_2 | Orange 
--------------------------- 
List_1 | item_3 | Pear 
--------------------------- 
List_2 | item_1 | Potatoes 
--------------------------- 
List_2 | item_2 | ... 

我有一個getNextItem()函數遞增ITEMID並使用SQL查詢來獲取下一個項目:

SELECT * FROM items_tbl 
WHERE listID = "$listId" 
AND itemID = "$itemID" 
LIMIT 1 

在SQL中有一個簡單的方法來弄清楚我所得到的項目是否是該列表中的最後一個?

我可以在表中添加一列並標記每個列表的最後一項,或者我可以進行另一個查詢,獲取最高的項目編號並與我的列表中的當前項目進行比較,或者獲取項目的總數該清單並跟蹤與清單總數相關的項目編號......但所有這些解決方案都像是黑客攻擊。

有人可以提出更好的SQL的東西,並解釋一下它是如何工作的?

+0

「last」和「next」是如何定義的?爲了找到「下一個」行,你排序哪一列?除非你使用ORDER BY,否則就不會有「下一個」行。 –

+0

@a_horse_with_no_name:函數getNextItem()遞增itemID,所以「next」表示具有列表中下一個itemID的項目。如果當前項目是蘋果,則下一個項目是橙色,最後一個項目是梨子。 – Sylverdrag

回答

0

你不說出你的DBMS,但下面是符合ANSI SQL(應PosgreSQL,甲骨文,DB2工作)

SELECT * 
FROM (
    SELECT listid, 
      itemid, 
      case 
       when lead(itemid) over (partition by listid order by itemid) is null then 'last' 
       else 'not_last' 
      end as last_flag 
    FROM items_tbl 
    WHERE listID = 'List_1' 
) t 
WHERE itemID = 'item_2' 

編輯,下面應該在SQL Server上運行(因爲沒有按尚未支持lead()):

SELECT listid, 
     itemid, 
     case 
     when rn = list_count the 'last' 
     else 'not_last' 
     end 
FROM (
    SELECT listid, 
      itemid, 
      row_number() over (partition by listid order by itemid) as rn, 
      count(*) over (partition by listid) as list_count 
    FROM items_tbl 
    WHERE listID = 'List_1' 
) t 
WHERE itemID = 'item_2' 
+0

謝謝。 DBMS是MySql,如「想象一個MySql表」;)。我找到了一個解決方案(請參閱我對Jan Vorcak的回答的評論)。我不明白你的解決方案如何工作。這個問題已經解決了,但是如果你能找到時間,我仍然會喜歡解釋 - 就像你所說的,我對SQL的知識是相當基礎的。 – Sylverdrag

+0

對不起,沒有看到提到的MySQL,正在尋找一個標籤。基本的想法是根據你定義的排序順序檢查是否有下一個記錄 - 這就是'lead'函數的作用。您可以閱讀PostgreSQL手冊,以便對窗口函數進行很好的介紹:http://www.postgresql.org/docs/9.1/static/tutorial-window.html –

+0

謝謝。我現在明白了。抱歉,我忘了將它作爲標籤。那麼,因爲在這個時候,你的答案是唯一能夠真正解答問題的答案,所以我會選擇它,並提出Vorcak的答案。 – Sylverdrag

0

做很可能是,你開始之前把最簡單的事情,得到最高的ID在每個列表:

Select listID, max(itemID) from mytable group by listID 
+0

我不確定(無論如何我們都在這裏學習),但如果有人更改表格(添加/刪除某行),那麼結果可能是他想要的,或者我錯了? –

+0

如果有人改變了桌子,那麼這可能會給出錯誤的數字,是的,但是我能想到的任何方法都不在我頭頂。最乾淨的事情是一次獲得單個列表的所有項目。如果你一次只需要一個,就將它們緩存起來。 – Kevin

+0

它會工作(我的列表不會改變),但是我必須跟蹤$ _SESSION中的數據,比較listID然後比較項目編號與總數。這是可行的,但沒有更好的方法嗎? – Sylverdrag

1

我一個自動增量的主鍵名爲id添加到您的表並使用嵌套的SQL查詢來獲取表

SELECT id, ListID, itemID, item, (SELECT MAX(id) FROM table_name) as max_id from table_name; 

這將返回你的表中的所有列有一個額外的命名max_id列具有最大ID的最大的ID,這樣你就可以在你的應用程序檢查是否max_id == ID,如果是的話它的最後一列

+0

這不會返回所有列表中的最後一個ID嗎?也就是說,我認爲嵌套的SQL查詢可能是票據。 – Sylverdrag

+0

使用你的子查詢的想法,我定的SQL請求:SELECT *,( SELECT MAX(ITEMID)FROM items_tbl WHERE listID = 「$ listID」 )作爲max_id FROM items_tbl WHERE listID = 「$ listID」 AND itemID =「$ itemID」 LIMIT 1;請修復您的答案,以便我可以接受它。 – Sylverdrag

相關問題