2009-07-16 10 views
60

私は、ユーザの現在のIPと1つ以上の先行する両方のIPを含む可能性のあるテーブルからip、user、および最新のタイムスタンプを取得しようとしていますips。私は、最新のIPと関連するタイムスタンプを含む各ユーザのために1行を希望します。表は次のようになりますのであれば:特定のキーのインスタンスごとに最新の行を取得するSQLクエリ

username  | ip  | time_stamp 
--------------|----------|-------------- 
ted   | 1.2.3.4 | 10 
jerry   | 5.6.6.7 | 12 
ted   | 8.8.8.8 | 30 

私は、クエリの出力があることを期待したい:

jerry | 5.6.6.7 | 12 
ted  | 8.8.8.8 | 30 

私は、単一のSQLクエリでこれを行うことができますか?重要な場合は、DBMSはPostgresqlです。このような何か

Select u.[username] 
     ,u.[ip] 
     ,q.[time_stamp] 
From [users] As u 
Inner Join (
    Select [username] 
      ,max(time_stamp) as [time_stamp] 
    From [users] 
    Group By [username]) As [q] 
On u.username = q.username 
And u.time_stamp = q.time_stamp 

答えて

90

はこれを試してみてください。

+0

私は正しい軌道に乗っていましたが、参加権が得られませんでした。これはトリックでした。ありがとう! – alanc10n

+2

これはSQL Serverで動作しますか?同様のデータで全く同じことを試しましたが、最新のタイムスタンプだけでなく、すべての "ip"の行を取得しています。 – tcash21

+0

HANAテーブルに対して使用すると、1が予想される複数の行が生成されました。 HANAには、一般的なSQLエンジンのほとんどと同じではない多くのものがあります。 –

7

select * 
from User U1 
where time_stamp = (
    select max(time_stamp) 
    from User 
    where username = U1.username) 

はそれを行う必要があります

+0

'time_stamp'がユニークで、あなたがそれを仮定することができないなら、それはうまくいくでしょう。 – Nux

3

上記の両方の回答は、各ユーザーとtime_stampに1つの行しかないと仮定しています。アプリケーションとtime_stampの細かさによっては、これは有効な前提ではないかもしれません。特定のユーザーのtime_stampの関係を処理する必要がある場合は、上記の答えの1つを拡張する必要があります。

このクエリを1つのクエリに書き込むには、別のネストされたサブクエリが必要です。状況がより乱雑になり、パフォーマンスが低下する可能性があります。

私はこれをコメントとして追加したことが大好きでしたが、私は50の評判をまだ持っていませんので、新しい回答として投稿してください!

+5

"両方の上記の..."は答えを開始する良い方法ではありません。上記の答えがあなたが参照しているものであるかどうかを私はどのように知るべきですか?回答はスコアに基づいて異なる順序で表示されます。 –

+6

ロブ、私はあなたが彼に知らないと言っているとは思わない。彼はコメントすることはできませんし、彼が言及していた答えは明らかに欠陥がありました。もっと重要なのは、テキストがどこに置かれたのか、知識や批評を伝えることですか? – cruskai239

0

私は別のテーブルから結果を返すため、これを使用しています。しかし、ネストされた結合を避けようとしているのですが、1つ少ないステップで助けてください。しかたがない。それは同じことを返します。

select 
users.userid 
, lastIP.IP 
, lastIP.maxdate 

from users 

inner join (
    select userid, IP, datetime 
    from IPAddresses 
    inner join (
     select userid, max(datetime) as maxdate 
     from IPAddresses 
     group by userid 
     ) maxIP on IPAddresses.datetime = maxIP.maxdate and IPAddresses.userid = maxIP.userid 
    ) as lastIP on users.userid = lastIP.userid 
+0

これは上記のユーザーの応答の答えですと考えています – jawz101

29

(PostgreSQLでサポート - SQL Fiddleに参照)ROW_NUMBER窓関数ニースエレガントな解決策に:

SELECT username, ip, time_stamp FROM (
SELECT username, ip, time_stamp, 
    ROW_NUMBER() OVER (PARTITION BY username ORDER BY time_stamp DESC) rn 
FROM Users 
) tmp WHERE rn = 1; 
+2

これはネストしたクエリの結合を含まないため、これが最良の答えです。問題は、キーに[ip]と質問ごとのユーザー名を含める必要があるだけです。 – dashnick

1

はまだコメントを投稿することはできませんが、@Cristi Sの答えは私のために御馳走を作品。

私のシナリオでは、最新の3つのレコードのみをすべてのproduct_idのLowest_Offersに保存する必要がありました。

削除するSQLを書き直す必要があります。これは問題ありませんが、構文は間違っていると思います。

DELETE from (
SELECT product_id, id, date_checked, 
    ROW_NUMBER() OVER (PARTITION BY product_id ORDER BY date_checked DESC) rn 
FROM lowest_offers 
) tmp WHERE > 3; 
+0

修正SQL:Lowest_Offer FROM DELETE WHERE ID date_checked DESC BY PRODUCT_ID ORDER)BY(PARTITION OVER \t FROM ( \t SELECT ID( \t \t SELECT PRODUCT_ID、ID、date_checked、 \t \t ROW_NUMBER()で \t \t RN FROM Lowest_Offer \t)tmp WHERE rn> 3 ) – err1

関連する問題