我有一个表,它是关于用户何时登录的集合条目。
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..
如何创建一个查询,为我提供每个用户的最新日期?
更新:我忘记了我需要一个与最新日期一致的值。
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
使用窗口函数(适用于 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
username
),甚至不需要唯一的“可排序”字段(如在其他答案中加入 max(date)
)。
order by date desc, id desc)
。
我看到大多数开发人员使用内联查询时没有考虑它对海量数据的影响。
简单地说,您可以通过以下方式实现:
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;
a
中具有最大日期的记录,b
中不会有任何更大的记录。
根据我的经验,最快的方法是获取表格中没有新行的每一行。
另一个优点是使用的语法非常简单,并且查询的含义相当容易掌握(获取所有行,使得所考虑的用户名不存在更新的行)。
不存在
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
SELECT username, value FROM t WHERE NOT EXISTS ( SELECT * FROM t AS witness WHERE witness.date > t.date AND witness.username = t.username );
要获取包含用户最大日期的整行:
select username, date, value
from tablename where (username, date) in (
select username, max(date) as date
from tablename
group by username
)
SELECT *
FROM MyTable T1
WHERE date = (
SELECT max(date)
FROM MyTable T2
WHERE T1.username=T2.username
)
这应该为您编辑的问题提供正确的结果。
子查询确保只找到最新日期的行,而外部 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
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
这类似于上面的答案之一,但在我看来,它更简单、更整洁。此外,还显示了交叉应用语句的良好用途。对于 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
您还可以使用分析排名函数
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
SELECT MAX(DATE) AS dates
FROM assignment
JOIN paper_submission_detail ON assignment.PAPER_SUB_ID =
paper_submission_detail.PAPER_SUB_ID
如果您的数据库语法支持它,那么 TOP 1 WITH TIES
可以与 ROWNUMER
结合使用更安全。
使用您提供的示例数据,使用以下查询:
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
这个怎么运作:
ROWNUMBER() OVER (PARTITION BY... ORDER BY...) 对于每个用户名,从最年轻的 (rownumber=1) 到最旧的 (rownumber=high) 计算行列表
ORDER BY ROWNUMBER... 将每个用户的最年轻的行排序到顶部,然后是每个用户的第二年轻的行,依此类推
TOP 1 WITH TIES 因为每个用户都有一个最年轻的行,所以这些最年轻的行在排序标准的意义上是相等的(所有行数=1)。所有那些最年轻的行都将被返回。
使用 SQL-Server 测试。
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
将解决更新的问题。即使有良好的索引,它在大型表上也可能效果不佳。
SELECT *
FROM ReportStatus c
inner join ( SELECT
MAX(Date) AS MaxDate
FROM ReportStatus ) m
on c.date = m.maxdate
对于Oracle,将结果集按降序排序并取第一条记录,因此您将获得最新的记录:
select * from mytable
where rownum = 1
order by date desc
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
Select * from table1 where lastest_date=(select Max(latest_date) from table1 where user=yourUserName)
内查询会返回当前用户的最新日期,外查询会根据内查询结果拉取所有数据。
我用这种方式为我桌子上的每个用户获取最后一条记录。这是根据最近在 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
SELECT * FROM TABEL1 WHERE DATE= (SELECT MAX(CREATED_DATE) FROM TABEL1)
我的小合集
自联接比嵌套选择更好
但是 group by 不会给你主键,这对于加入来说更可取
这个键可以通过 partition by 与 first_value (docs) 一起给出
所以,这里有一个查询:
select t.* from Table t inner join ( select distinct first_value(ID) over(partition by GroupColumn order by DateColumn desc) as ID from Table where FilterColumn = 'value' ) j on t.ID = j.ID
优点:
使用任何列使用 where 语句过滤数据
从过滤的行中选择任何列
缺点:
从 2012 年开始需要 MS SQL Server。
我为我的应用程序做了一些事情,因为它:
以下是查询:
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));
您将使用聚合函数 MAX 和 GROUP BY
SELECT username, MAX(date), value FROM tablename GROUP BY username, value
value
,而不是与 MAX(date)
行关联的那个。
max(date)
将返回一个可以连接多个记录的日期)。为避免此问题,最好使用@dotjoe 的解决方案:stackoverflow.com/a/2411763/4406793。