web-dev-qa-db-ja.com

WHERE条件でSQLの最後のレコードを取得する

2つのフィールドloan_idloanTableを含むstatusがあります

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

この状況では、loan_id1の最後のStatusを表示する必要があります。つまり、status4です。このクエリで私を助けてください。

8
Dinup Kandel

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);

(DBMSまたは経験豊富なSQLプログラマーを混乱させることなく、テーブルエイリアスL1およびL2を省略できます。)

現状では、どちらが最後の行であるかを確実に知る方法がないため、クエリに回答できません。

16

テーブルにプライマリIDまたはタイムスタンプがありますか?そうでなければ、あなたが望むことは実際には不可能です。

はいの場合:

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

「最後のステータス」とは、最近挿入されたレコードを意味すると思いますか? AFAIKは、レコードが追加された日時を格納するテーブルにタイムスタンプを追加しない限り、このようなクエリを実行する方法はありません。 RDBMSは、レコードの内部順序を保持しません。

4
ain

ただし、last = last insertの場合、PKが追加されるまで、現在のスキーマでは不可能です。

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

識別列がない場合は、挿入順序を取得するために使用できます。あなたはいつでもこのようにそれを行うことができます。しかし、それはハッキーで、あまりきれいではありません。

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

したがって、基本的には、それを呼び出すことができれば「自然な順序」を取得し、すべて同じデータを含む列を追加します。これを使用して「自然順序」で並べ替えることができ、次のクエリで行番号列を配置する機会が与えられます。

個人的には、使用しているシステムにタイムスタンプ/ ID列がなく、現在のユーザーが「自然順序」を使用している場合は、すぐに列を追加し、このクエリを使用して、ある種のタイムスタンプ/増分を作成します。キー。自動化メカニズムによって「自然な順序」が変更されるリスクを冒すのではなく、必要なデータを破壊します。

0

Oracleデータベースでは、これは非常に簡単です。

select * from(select * from LoanTable order by rownum desc)where rownum = 1

0
Gyan

データリーダーを使用します。 whileループを終了すると、最後の行になります。他のポスターが述べているように、クエリに並べ替えを行わない限り、行の順序が変わる可能性があります。テーブルにクラスター化インデックスがある場合でも、(クラスター化インデックスの並べ替えなしで)その順序で行が返されない場合があります。

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

ROW_NUMBER()を使用することもできますが、これには並べ替えが必要であり、WhereでROW_NUMBER()を直接使用することはできません。しかし、派生テーブルを作成することでそれをだますことができます。上記のrdrソリューションの方が高速です。

0
paparazzo

私はこのコードがあなたを助けるかもしれないと思います:

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)
0
vamsi

こんにちは、これがまだ解決されていない場合。テーブルから任意のフィールドの最後のレコードを取得する最も簡単な方法は、各レコードにID(pIDなど)を追加することです。また、テーブルで「名前」ごとに最後のレコードを取得したい場合は、単純なクエリを実行します。

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]    

これで、1つの列に名前と、その名前で使用可能な最後の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

これにより、各名前の最後のレコードが得られます。最初のレコードでは、上記と同じクエリを実行し、上記の最大値を最小値に置き換えます。

これは簡単に実行でき、実行も速くなるはずです。

0
Jabu