SQL使用GROUP BY查找最近的行

SQL使用GROUP BY查找最近的行,sql,Sql,SQL新手听到我在努力解决这个问题!我有一个类似的问题 我有以下数据,所有字段都被定义为字符-没有日期或时间,很遗憾,这要感谢原始DBA糟糕的设计 Surname Name LoginDate LoginTime Smith John 2014-06-25 13.00 Smith John 2014-06-24 14.00 Smith Susan 2014-06-26 09.00 Smith Susan

SQL新手听到我在努力解决这个问题!我有一个类似的问题

我有以下数据,所有字段都被定义为字符-没有日期或时间,很遗憾,这要感谢原始DBA糟糕的设计

Surname    Name     LoginDate   LoginTime

Smith      John     2014-06-25  13.00
Smith      John     2014-06-24  14.00 
Smith      Susan    2014-06-26  09.00
Smith      Susan    2014-06-26  11.30
Jones      Bill     2014-06-25  09.30
Jones      Bill     2014-06-25  12.30
Jones      Bill     2014-06-26  07.00
我试图从我的输出中得到的是每个人最近的登录,所以我希望看到

Smith      John     2014-06-25  13.00
Smith      Susan    2014-06-26  11.30
Jones      Bill     2014-06-26  07.00
我尝试过临时表的不同组合,在日期和时间上使用CONCAT和MAX函数,但我一直在画空白。我想我知道我需要使用的工具和命令,但我似乎无法将它们正确地串在一起

我知道我必须按名称/姓氏对它们进行分组,然后以某种方式组合日期和时间,以便使用MAX函数,但当我输出它们时,我似乎永远无法使LoginDate和LoginTime在输出上显示为单独的字段,因为它们不包括在我使用的任何组中

有人能告诉我怎么做吗,因为我一开始没有很多头发:

你不能使用分组方式。以下是使用“不存在”的方法:

这会将查询转换为:获取表中没有同名行的所有行并稍后登录。如果登录信息存储为单个日期时间,则会更简单


此外,上述内容将适用于几乎所有的SQL数据库。许多数据库支持窗口函数,这些函数也可用于解决此问题。

除了Gordon Linoff的答案之外,如果SQL数据库支持窗口函数,您还可以使用它来获得所需的结果:

;With Cte As
(
    Select  *, 
            Row_Number() Over (Partition By Surname, Name Order By LoginDate Desc, LoginTime Desc) RN
    From    Table
)
Select  Surname, Name, LoginDate, LoginTime
From    Cte
Where   RN = 1
请尝试此查询-

With MaxTimeStamp as 
(
 SELECT Surname, Name, Max(TIMESTAMP(LoginDate, LoginTime)) as LoginDateTime
 FROM   YourTable 
 group by Surname, Name
)
select c.Surname, c.Name, d.LoginDate, d.LoginTime,
from MaxTimeStamp c 
Join  YourTable d 
      on  c.Surname = d.Surname
      and  c.Name       = d.Name
      and  Date(c.LoginDateTime)    = d.LoginDate
      and  Time(c.LoginDateTime)    = d.LoginTime

为什么不是一个小组?我遗漏了什么

从表中选择名称、姓氏、登录名、maxLoginTime,其中按名称从表组中选择名称、姓氏、maxLoginDate,按名称从表组中选择姓氏、姓氏、maxLoginTime,按名称从姓氏组中选择姓氏、登录名、登录名

如果LoginDate不是日期或类似的数据类型,我想它应该运行


Br.

我将其分为两部分,以查找每个用户的最新登录名并按进行分组。然后我再次加入数据以查找记录

select 
    dt.Surname
    , dt.Name
    , dt.LoginDate
    , dt.LoginTime 
from 
    dataTable dt 
    join
        (select Surname, Name, MAX(LoginDate+LoginTime) ts from #temp group by surname, name) sub 
        on sub.Name = dt.Name
        and sub.Surname = dt.Surname
    and dt.LoginDate+dt.LoginTime = ts
WHERE
    not sub.Name is null
您还可以通过再次拆分时间戳来完成此操作,而无需加入

select 
    sub.Surname
    , sub.Name
    , LEFT(ts,10) LoginDate
    , RIGHT(ts,5) LoginTime 
from 
    (select Surname, Name, MAX(LoginDate+LoginTime) ts from #temp group by surname, name) sub 

您使用的是什么sql平台?Sql Server?我的SQL?神谕等等,LoginDate和LoginTime是什么数据类型?如果它们是一个字段作为DateTime,那就容易多了……这是在AS400上,不幸的是,日期和时间字段被定义为字符而不是日期或时间。我知道这是一个糟糕的设计,但这就是我必须处理的问题。如果以这种方式工作,我们的生活就会变得容易多了凉的很高兴知道它在Oracle中工作。谢谢你增加了我的甲骨文词汇量。
select 
    sub.Surname
    , sub.Name
    , LEFT(ts,10) LoginDate
    , RIGHT(ts,5) LoginTime 
from 
    (select Surname, Name, MAX(LoginDate+LoginTime) ts from #temp group by surname, name) sub