2011-11-26 105 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

相关问题