在WHERE条件中获取SQL中的最后一条记录

时间:2011-08-07 10:46:19

标签: sql sql-server tsql where-clause

我的loanTable包含两个字段loan_idstatus

loan_id status
==============
1       0
2       9
1       6
5       3
4       5
1       4  <-- How do I select this??
4       6

在这种情况下,我需要显示Status的最后一个loan_id 1,即status 4.请在此查询中帮助我。

9 个答案:

答案 0 :(得分:14)

由于ID 1的“最后”行既不是最小值也不是最大值,因此您处于轻度混乱的状态。表中的行没有订单。因此,您应该提供另一列,可能是插入每行的日期/时间,以提供数据的排序。另一个选项可以是一个单独的,自动递增的列,它记录插入行的顺序。然后可以编写查询。

如果额外的列被称为status_id,那么你可以写:

SELECT L1.*
  FROM LoanTable AS L1
 WHERE L1.Status_ID = (SELECT MAX(Status_ID)
                         FROM LoanTable AS L2
                        WHERE L2.Loan_ID = 1);

(可以省略表别名L1和L2而不会混淆DBMS或经验丰富的SQL程序员。)

就目前而言,没有可靠的方法可以知道哪一行是最后一行,因此您的查询无法回答。

答案 1 :(得分:5)

您的表是否恰好有主ID或时间戳?如果不是那么你想要的东西真的不可能。

如果是,那么:

    SELECT TOP 1 status
    FROM loanTable
    WHERE loan_id = 1
    ORDER BY primaryId DESC
    -- or
    -- ORDER BY yourTimestamp DESC

答案 2 :(得分:4)

我认为“最后状态”是指最近插入的记录? AFAIK无法进行此类查询,除非您在表中添加时间戳,您可以在其中存储添加记录的日期和时间。 RDBMS不保留记录的任何内部顺序。

答案 3 :(得分:2)

但是如果last = last insert,那么当前架构是不可能的,直到PK添加:

select top 1 status, loan_id
from loanTable
where loan_id = 1
order by id desc -- PK

答案 4 :(得分:0)

使用数据阅读器。当它退出while循环时,它将在最后一行。正如其他海报所述,除非您对查询进行排序,否则行顺序可能会发生变化。即使表上存在聚簇索引,它也可能不会按该顺序返回行(不对聚簇索引进行排序)。

    SqlDataReader rdr = SQLcmd.ExecuteReader();
    while (rdr.Read())
    {
    }
    string lastVal = rdr[0].ToString()
    rdr.Close();

你也可以使用ROW_NUMBER(),但需要排序,你不能直接在Where中使用ROW_NUMBER()。但是你可以通过创建派生表来欺骗它。上面的rdr解决方案更快。

答案 5 :(得分:0)

在oracle数据库中,这非常简单。

选择* from(从rownum desc选择*来自loanTable的顺序)rownum = 1

答案 6 :(得分:0)

嗨,如果还没有解决的话。 要从表中获取任何字段的最后一条记录,最简单的方法是为每条记录添加一个ID,即pID。还要说在你的表中你想要为每个'Name'记录最后一条记录,运行简单的查询

SELECT Name, MAX(pID) as LastID
INTO [TableName]
FROM [YourTableName]
GROUP BY [Name]/[Any other field you would like your last records to appear by]    

您现在应该有一个表,其中包含一列中的名称以及该名称的最后一个可用ID。 现在,您可以使用联接从主表中获取其他详细信息,例如这是某个价格或日期,然后执行以下操作:

SELECT a.*,b.Price/b.date/b.[Whatever other field you want]
FROM [TableName] a LEFT JOIN [YourTableName] 
ON a.Name = b.Name and a.LastID = b.pID

然后,这应该为您提供每个名称的最后记录,对于第一个记录运行与上面相同的查询,只需替换上面的Max by Min。

这应该很容易理解,并且应该更快地运行

答案 7 :(得分:0)

如果您没有任何标识列,则可以使用它来获取插入顺序。你可以这样做。但这很黑,而且不是很漂亮。

select
t.row1,
t.row2,
ROW_NUMBER() OVER (ORDER BY t.[count]) AS rownum from (
select 
    tab.row1,
    tab.row2,
    1 as [count] 
from table tab) t

所以基本上你得到'自然顺序',如果你可以调用它,并添加一些包含所有相同数据的列。这可用于按“自然顺序”排序,使您有机会在下一个查询中放置行号列。

就个人而言,如果您使用的系统没有时间戳/标识列,并且当前用户正在使用“自然顺序”,我会快速添加一列并使用此查询创建某种时间邮票/增量键。而不是冒着让某些自动化机制改变“自然顺序”的风险,而是打破所需的数据。

答案 8 :(得分:0)

我认为此代码可能会对您有所帮助:

WITH cte_Loans
AS
(
SELECT   LoanID
        ,[Status]
        ,ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS RN
FROM    LoanTable
)

SELECT   LoanID
        ,[Status]
FROM    LoanTable L1
WHERE   RN = (  SELECT max(RN)
                FROM LoanTable L2
                WHERE L2.LoanID = L1.LoanID)