315

我有一个表,它是关于用户何时登录的集合条目。

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..

如何创建一个查询,为我提供每个用户的最新日期?

更新:我忘记了我需要一个与最新日期一致的值。

4

23 回答 23

493
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
于 2010-03-09T18:56:12.790 回答
178

使用窗口函数(适用于 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
于 2010-03-09T19:05:04.113 回答
42

我看到大多数开发人员使用内联查询时没有考虑它对海量数据的影响。

简单地说,您可以通过以下方式实现:

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;
于 2016-08-18T11:20:20.593 回答
27

要获取包含用户最大日期的整行:

select username, date, value
from tablename where (username, date) in (
    select username, max(date) as date
    from tablename
    group by username
)
于 2010-03-09T18:54:15.660 回答
25

根据我的经验,最快的方法是获取表格中没有新行的每一行。

另一个优点是使用的语法非常简单,并且查询的含义相当容易掌握(获取所有行,使得所考虑的用户名不存在更新的行)。

不存在

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

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

内部联接

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;

左外连接

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
于 2018-08-22T12:28:46.020 回答
11
SELECT *     
FROM MyTable T1    
WHERE date = (
   SELECT max(date)
   FROM MyTable T2
   WHERE T1.username=T2.username
)
于 2013-06-03T14:00:16.200 回答
2

这应该为您编辑的问题提供正确的结果。

子查询确保只找到最新日期的行,外部GROUP BY将处理关系。当同一用户在同一日期有两个条目时,它将返回具有最高 的条目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
于 2010-03-09T18:54:11.103 回答
1
SELECT DISTINCT Username, Dates,value 
FROM TableName
WHERE  Dates IN (SELECT  MAX(Dates) FROM TableName GROUP BY Username)


Username    Dates       value
bob         2010-02-02  1.2       
brad        2010-01-02  1.1       
fred        2010-01-03  1.0       
于 2015-07-27T13:41:16.067 回答
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
于 2018-08-20T06:36:14.507 回答
1

您还可以使用分析排名函数

    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
于 2018-09-26T01:42:15.790 回答
1

如果您的数据库语法支持它,那么TOP 1 WITH TIESROWNUMER.

使用您提供的示例数据,使用以下查询:

SELECT TOP 1 WITH TIES
  username, date, value
FROM user_log_in_attempts
ORDER BY ROW_NUMBER() OVER (PARTITION BY username ORDER BY date DESC)

它产生:

username | date      | value
-----------------------------
bob      | 8/4/2009  | 1.5
brad     | 2/2/2010  | 1.2
fred     | 12/2/2009 | 1.3

Demo

这个怎么运作:

  • ROWNUMBER() OVER (PARTITION BY... ORDER BY...)对于每个用户名,从最年轻的 (rownumber=1) 到最旧的 (rownumber=high) 计算行列表
  • ORDER BY ROWNUMBER...将每个用户的最年轻的行排在最前面,然后是每个用户的第二年轻的行,依此类推
  • TOP 1 WITH TIES因为每个用户都有一个最年轻的行,所以这些最年轻的行在排序标准的意义上是相等的(所有行数=1)。所有那些最年轻的行都将被返回。

使用 SQL-Server 测试。

于 2021-10-26T17:00:34.783 回答
0
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

将解决更新的问题。即使有良好的索引,它在大型表上也可能效果不佳。

于 2010-03-09T18:53:52.510 回答
0
SELECT *
FROM ReportStatus c
inner join ( SELECT 
  MAX(Date) AS MaxDate
  FROM ReportStatus ) m
on  c.date = m.maxdate
于 2012-12-18T10:54:00.873 回答
0
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
于 2014-12-02T21:06:10.553 回答
0

对于Oracle,将结果集按降序排序并取第一条记录,因此您将获得最新的记录:

select * from mytable
where rownum = 1
order by date desc
于 2015-03-05T19:26:06.517 回答
0

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

内查询会返回当前用户的最新日期,外查询会根据内查询结果拉取所有数据。

于 2017-01-04T10:12:54.950 回答
0

我用这种方式为我桌子上的每个用户获取最后一条记录。这是根据最近在 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
于 2017-02-27T13:18:19.950 回答
0
SELECT * FROM TABEL1 WHERE DATE= (SELECT MAX(CREATED_DATE) FROM TABEL1)
于 2017-05-29T11:22:50.693 回答
0

我的小合集

  • 自我join优于嵌套select
  • group by没有给你primary key哪个更适合join
  • 这个键可以partition byfirst_value( docs )一起给出

所以,这里有一个查询:

选择
 t.*
从
 表 t 内连接 (
  select distinct first_value(ID) over(partition by GroupColumn order by DateColumn desc) 作为 ID
  从表
  其中 FilterColumn = '值'
 ) j 上 t.ID = j.ID

优点:

  • where使用任何列使用语句过滤数据
  • select过滤行中的任何列

缺点:

  • 从 2012 年开始需要 MS SQL Server。
于 2017-08-23T04:55:44.617 回答
0

我为我的应用程序做了一些事情,因为它:

以下是查询:

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));    
于 2018-08-07T12:02:37.687 回答
0
SELECT MAX(DATE) AS dates 
FROM assignment  
JOIN paper_submission_detail ON  assignment.PAPER_SUB_ID = 
     paper_submission_detail.PAPER_SUB_ID 
于 2020-05-20T13:11:34.243 回答
-2

这也应该可以为用户获取所有最新条目。

SELECT username, MAX(date) as Date, value
FROM MyTable
GROUP BY username, value
于 2016-02-05T06:00:41.580 回答
-6

您将使用聚合函数 MAX 和 GROUP BY

SELECT username, MAX(date), value FROM tablename GROUP BY username, value
于 2010-03-09T18:37:36.757 回答