【问题标题】:Get last item in a table - SQL获取表中的最后一项 - SQL
【发布时间】:2010-09-06 23:43:48
【问题描述】:

我在 SQL Server 中有一个历史表,它基本上通过一个进程跟踪项目。该项目有一些在整个过程中不会更改的固定字段,但还有一些其他字段,包括状态和 Id,它们会随着过程步骤的增加而增加。

基本上,我想检索给定批次参考的每个项目的最后一步。所以如果我做一个

Select * from HistoryTable where BatchRef = @BatchRef

它将返回批处理中所有项目的所有步骤 - 例如

Id 状态 BatchRef ItemCount 1 1 批次001 100 1 2 批次001 110 2 1 批次001 60 2 2 批次001 100

但我真正想要的是:

Id 状态 BatchRef ItemCount 1 2 批次001 110 2 2 批次001 100

编辑:Appologies - 似乎无法让 TABLE 标签与 Markdown 一起使用 - 遵循帮助,在预览中看起来很好

【问题讨论】:

    标签: sql sql-server database tsql


    【解决方案1】:

    假设您在表中有一个标识列...

    select 
        top 1 <fields> 
    from 
        HistoryTable 
    where 
        BatchRef = @BatchRef 
    order by 
        <IdentityColumn> DESC
    

    【讨论】:

      【解决方案2】:

      很难理解您的表格设计 - 我认为 SO 吃了您的分隔符。

      处理此问题的基本方法是对您的固定字段进行分组,并为某些 unqiue 值选择一个 MAX(或 MIN)(日期时间通常效果很好)。在您的情况下,我认为 GROUP BY 将是 BatchRef 和 ItemCount,而 Id 将是您的唯一列。

      然后,连接回表以获取所有列。比如:

      SELECT * 
      FROM HistoryTable
      JOIN (
         SELECT 
             MAX(Id) as Id.
             BatchRef,
             ItemCount
         FROM HsitoryTable
         WHERE
             BacthRef = @batchRef
         GROUP BY
             BatchRef,
             ItemCount
       ) as Latest ON
         HistoryTable.Id = Latest.Id
      

      【讨论】:

        【解决方案3】:

        假设项目 ID 是递增编号的:

        --Declare a temp table to hold the last step for each item id
        DECLARE @LastStepForEach TABLE (
        Id int,
        Status int,
        BatchRef char(10),
        ItemCount int)
        
        --Loop counter
        DECLARE @count INT;
        SET @count = 0;
        
        --Loop through all of the items
        WHILE (@count < (SELECT MAX(Id) FROM HistoryTable WHERE BatchRef = @BatchRef))
        BEGIN
            SET @count = @count + 1;
        
            INSERT INTO @LastStepForEach (Id, Status, BatchRef, ItemCount)
                SELECT Id, Status, BatchRef, ItemCount
                FROM HistoryTable 
                WHERE BatchRef = @BatchRef
                AND Id = @count
                AND Status = 
                (
                    SELECT MAX(Status) 
                    FROM HistoryTable 
                    WHERE BatchRef = @BatchRef 
                    AND Id = @count
                )
        
        END
        
        SELECT * 
        FROM @LastStepForEach
        

        【讨论】:

          【解决方案4】:
          SELECT id, status, BatchRef, MAX(itemcount) AS maxItemcount 
          FROM HistoryTable GROUP BY id, status, BatchRef 
          HAVING status > 1 
          

          【讨论】:

          • 通过标记东西 wiki 你剥夺了你自己的代表,一般来说没有必要。这个答案的工作
          【解决方案5】:

          使用 WMD 格式化数据的方式解密数据有点困难,但您可以使用 SQL 2005 上的常用表表达式来获得所需的技巧:

          with LastBatches as (
              select Batch, max(Id)
              from HistoryTable
              group by Batch
          )
          select *
          from HistoryTable h
              join LastBatches b on b.Batch = h.Batch and b.Id = h.Id
          

          或子查询(假设子查询中的 group by 有效 - 我不记得了):

          select *
          from HistoryTable h
              join (
                  select Batch, max(Id)
                  from HistoryTable
                  group by Batch
              ) b on b.Batch = h.Batch and b.Id = h.Id
          

          编辑:我假设您想要批次的最后一个项目。如果您只需要一批,那么其他答案(排名前 1 位并按降序排列)是可行的方法。

          【讨论】:

            【解决方案6】:

            正如已经建议的那样,您可能希望重新排序查询以将其按另一个方向排序,以便实际获取第一行。那么你可能想要使用类似的东西

            SELECT TOP 1 ...
            

            如果您使用的是 MSSQL 2k 或更早版本,或者 SQL 兼容变体

            SELECT * FROM (
              SELECT
                ROW_NUMBER() OVER (ORDER BY key ASC) AS rownumber,
                columns
              FROM tablename
            ) AS foo
            WHERE rownumber = n
            

            对于任何其他版本(或对于支持标准符号的其他数据库系统),或

            SELECT ... LIMIT 1 OFFSET 0
            

            对于没有标准 SQL 支持的其他一些变体。

            另请参阅this question,了解有关选择行的更多讨论。根据计算值是否需要表扫描,使用聚合函数 max() 可能更快也可能不会更快。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-04-28
              • 2011-03-14
              • 2010-10-13
              • 1970-01-01
              • 2022-07-22
              相关资源
              最近更新 更多