web-dev-qa-db-ja.com

どのように私は各ユーザーの最新の記録日をSQLに問い合わせるのですか

ユーザーがいつログオンしたかに関するコレクションエントリであるテーブルがあります。

username, date,      value
--------------------------
brad,     1/2/2010,  1.1
fred,     1/3/2010,  1.0
bob,      8/4/2009,  1.5
brad,     2/2/2010,  1.2
fred,     12/2/2009, 1.3

etc..

各ユーザーの最新の日付を表示するクエリを作成する方法を教えてください。

更新:最新の日付に沿った値を設定する必要があることを忘れました。

173
fishhead
select t.username, t.date, t.value
from MyTable t
inner join (
    select username, max(date) as MaxDate
    from MyTable
    group by username
) tm on t.username = tm.username and t.date = tm.MaxDate
297
RedFilter

ウィンドウ関数を使用する(Oracle、Postgres 8.4、SQL Server 2005、DB2、Sybase、Firebird 3.0、MariaDB 10.3で動作します)

select * from (
    select
        username,
        date,
        value,
        row_number() over(partition by username order by date desc) as rn
    from
        yourtable
) t
where t.rn = 1
79
dotjoe

大部分の開発者は、巨大なデータへの影響を考慮せずにインラインクエリを使用しています。

簡単に言うと、これを達成することができます。

SELECT a.username, a.date, a.value
FROM myTable a
LEFT OUTER JOIN myTable b
ON a.username = b.username 
AND a.date < b.date
WHERE b.username IS NULL
ORDER BY a.date desc;
33
sujeet

ユーザーの最大日付を含む行全体を取得するには、次の手順を実行します。

select username, date, value
from tablename where (username, date) in (
    select username, max(date) as date
    from tablename
    group by username
)
19
Alison R.
SELECT *     
FROM MyTable T1    
WHERE date = (
   SELECT max(date)
   FROM MyTable T2
   WHERE T1.username=T2.username
)
7
Manix

これにより、編集した質問に対して正しい結果が得られます。

サブクエリは必ず最新の日付の行だけを見つけるようにし、外側のGROUP BYは関係を処理します。同じユーザーの同じ日付に2つのエントリがある場合は、最も高いvalueを持つエントリが返されます。

SELECT t.username, t.date, MAX( t.value ) value
FROM your_table t
JOIN (
       SELECT username, MAX( date ) date
       FROM your_table
       GROUP BY username
) x ON ( x.username = t.username AND x.date = t.date )
GROUP BY t.username, t.date
2
Peter Lang

分析ランク関数も使用できます

    with temp as 
(
select username, date, RANK() over (partition by username order by date desc) as rnk from t
)
select username, rnk from t where rnk = 1
1
imba22

私の経験上、最も早い方法は、テーブルに新しい行がない各行を取得することです。これは私が手元にあるいくつかのデータを使った小さなベンチマークです。

もう1つの利点は、使用される構文が非常に単純であること、およびクエリの意味がかなり把握しやすいことです(検討対象のユーザー名に対して新しい行が存在しないようにすべての行を取得する)。

存在しません

SELECT username, value
FROM t
WHERE NOT EXISTS (
  SELECT *
  FROM t AS witness
  WHERE witness.date > t.date
);

説明費用の合計:2.38136

ROW_NUMBER

SELECT username, value
FROM (
  SELECT username, value, row_number() OVER (PARTITION BY username ORDER BY date DESC) AS rn
  FROM t
) t2
WHERE rn = 1

トータルコスト:61.5823

内部結合

SELECT t.username, t.value
FROM t
INNER JOIN (
  SELECT username, MAX(date) AS date
  FROM t
  GROUP BY username
) tm ON t.username = tm.username AND t.date = tm.date;

説明費用合計:67.5439

左外部結合

SELECT username, value
FROM t
LEFT OUTER JOIN t AS w ON t.username = w.username AND t.date < w.date
WHERE w.username IS NULL

説明費用の合計:62.964


EXPLAIN PLANは、XMLとして格納された約1万行のデータベースから取得されます。使用されるクエリには、述語 "group_id = '1'"も含まれています。

1
Fabian Pijcke

Select * from table1 where lastest_date=(select Max(latest_date) from table1 where user=yourUserName)

Inner Queryは現在のユーザーの最新の日付を返します。Outerqueryは、内部クエリの結果に従ってすべてのデータを取得します。

0
Dheeraj Kumar

Oracleの場合、結果セットは降順でソートされ、最初のレコードが取得されるため、最新のレコードが取得されます。

select * from mytable
where rownum = 1
order by date desc
0
user2014518

この方法を使用して、自分のテーブルにある各ユーザーの最後のレコードを取得しました。 PDAデバイスで最近検出された時間に、セールスマンの最後の場所を取得するためのクエリでした。

CREATE FUNCTION dbo.UsersLocation()
RETURNS TABLE
AS
RETURN
Select GS.UserID, MAX(GS.UTCDateTime) 'LastDate'
From USERGPS GS
where year(GS.UTCDateTime) = YEAR(GETDATE()) 
Group By GS.UserID
GO
select  gs.UserID, sl.LastDate, gs.Latitude , gs.Longitude
        from USERGPS gs
        inner join USER s on gs.SalesManNo = s.SalesmanNo 
        inner join dbo.UsersLocation() sl on gs.UserID= sl.UserID and gs.UTCDateTime = sl.LastDate 
        order by LastDate desc
0
Mahmoud Hawa
SELECT t1.username, t1.date, value
FROM MyTable as t1
INNER JOIN (SELECT username, MAX(date)
            FROM MyTable
            GROUP BY username) as t2 ON  t2.username = t1.username AND t2.date = t1.date
0
David
SELECT *
FROM ReportStatus c
inner join ( SELECT 
  MAX(Date) AS MaxDate
  FROM ReportStatus ) m
on  c.date = m.maxdate
0
Narmadha
SELECT * FROM TABEL1 WHERE DATE= (SELECT MAX(CREATED_DATE) FROM TABEL1)
0
AJAY
SELECT Username, date, value
 from MyTable mt
 inner join (select username, max(date) date
              from MyTable
              group by username) sub
  on sub.username = mt.username
   and sub.date = mt.date

更新された問題に対処します。優れた索引付けがあっても、大きなテーブルではそれほどうまくいかないかもしれません。

0
Philip Kelley

これは上記の答えの1つに似ていますが、私の意見ではそれははるかに単純で整頓されています。また、クロス適用ステートメントの有用な使用方法を示しています。 SQL Server 2005以降の場合.

select
    a.username,
    a.date,
    a.value,
from yourtable a
cross apply (select max(date) 'maxdate' from yourtable a1 where a.username=a1.username) b
where a.date=b.maxdate
0
James Moore

私の小さなコンピレーション

  • ネストしたjoinよりもself selectの方が優れています
  • しかしgroup byprimary keyを与えません。これはjoinには望ましいです
  • このキーは、partition byと組み合わせてfirst_valueで指定できます( docs

だから、これはクエリです:

 
から
 t。* 
を選択します。Table t内部結合(
を選択します。 FilterColumn = 'value'からID 
としてID 
 t.ID = j.ID 

長所:

  • 任意の列を使用してwhereステートメントでデータをフィルター処理する
  • selectフィルター処理された行の任意の列

短所:

  • 2012年からMS SQL Serverが必要です。
0
resnyanskiy

私はそれが私のアプリケーションのためにややしました:

以下はそのクエリです。

select distinct i.userId,i.statusCheck, l.userName from internetstatus 
as i inner join login as l on i.userID=l.userID 
where nowtime in((select max(nowtime) from InternetStatus group by userID));    
0
Sajee