Mysql 计算SQL中一组项的最后一项

Mysql 计算SQL中一组项的最后一项,mysql,sql,Mysql,Sql,设想一个MySql表,如下所示: --------------------------- ListID | itemID | Item --------------------------- List_1 | item_1 | Apple --------------------------- List_1 | item_2 | Orange --------------------------- List_1 | item_3 | Pear --------------------------

设想一个MySql表,如下所示:

---------------------------
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并解释一下它是如何工作的吗?

最简单的方法可能是,在开始之前,在每个列表中获得最高的id:

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

我将向表中添加一个名为id的自动递增主键,并使用嵌套的SQL查询来获取表的最大id

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

这将返回表中的所有列以及一个名为max_id且具有最大id的附加列,因此您可以在应用程序中检查max_id==id,如果是,则它是最后一列。您没有声明DBMS,但以下是符合ANSI标准的SQL应可用于PosgreSQL、Oracle、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:


我不确定我们是否都在这里学习,但如果有人更改表格添加/删除某行,结果可能会是他想要的其他结果,或者我错了吗?如果有人更改表格,那么这可能会给出错误的数字,是的,但我能想到的任何方法也会一样。最干净的方法是一次获取单个列表中的所有项目。如果您确实一次只需要一个,请缓存它们。如果我的列表不发生更改,这会起作用,但是我必须在$\u会话中跟踪数据,比较listID,然后将项目编号与总数进行比较。这是可行的,但是没有更好的方法吗?如果我要缓存完整的列表,我可能会完全跳过数据库,在PHP数组中使用每个列表和每个语言的一个平面文件,并包含相关文件。这也行,但感觉不对。难道没有一点SQL魔法可以帮我做到这一点吗?这不会返回所有列表组合中的最后一个ID吗?这就是说,我认为嵌套的SQL查询可能就是一张罚单。根据您对子查询的想法,我修复了SQL请求:SELECT*,SELECT MAXitemID FROM items\u tbl,其中listID=$listID作为最大id FROM items\u tbl,其中listID=$listID和itemID=$itemID LIMIT 1;请修改你的答案,这样我就可以接受了。上一个和下一个是如何定义的?按哪列排序以查找下一行?除非您使用ORDER BY,否则没有下一行。@a_horse_with_no_name:函数getNextItem会增加itemID,因此next表示列表中具有下一个itemID的项目。如果当前项为苹果,则下一项为橙色,最后一项为梨。谢谢。DBMS是MySql,就像在MySql表中一样;。我找到了一个解决方案,请参见我对Jan Vorcak回答的评论。我不明白你的解决方案是如何运作的。问题已经解决了,但是如果你能找到时间的话,我还是想得到一个解释,你可以说,我对SQL的知识比较基础,对不起,没有看到提到MySQL,我在找标签。基本思想是根据您定义的排序顺序检查是否有下一条记录-这就是lead函数所做的。您可以阅读PostgreSQL手册,了解窗口功能的详细介绍:谢谢。我现在明白了。很抱歉,我忘了把它作为标签。好吧,因为在这个时候你的答案是唯一一个真正能回答问题的答案,我会选择它并投票给沃卡克的答案。
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'