【问题标题】:Get latest sql rows based on latest date and per user根据最新日期和每个用户获取最新的 sql 行
【发布时间】:2013-11-22 14:40:54
【问题描述】:

我有下表:

RowId, UserId, Date
1, 1, 1/1/01
2, 1, 2/1/01
3, 2, 5/1/01
4, 1, 3/1/01
5, 2, 9/1/01

我想根据日期和UserId 获取最新记录,但作为以下查询的一部分(由于某种原因,我无法更改此查询,因为它是由工具自动生成的,但我可以编写传递任何以AND开头的东西...):

SELECT RowId, UserId, Date
FROM MyTable
WHERE 1 = 1
AND ( 

// everything which needs to be done goes here . . .

)

我尝试过similar query,但出现错误:

当不使用 EXISTS 引入子查询时,选择列表中只能指定一个表达式。

编辑:数据库是 Sql Server 2008

【问题讨论】:

  • 您使用的是哪个数据库服务器?
  • per UserID 表示您要按UserID 分组。您想如何仅使用 Where 子句进行分组?
  • 数据库是 sql server 2008,是的,我想按 user_id 分组,可以用任何方式完成。

标签: sql


【解决方案1】:

您可以使用NOT EXISTS 条件:

SELECT RowId, UserId, Date
FROM MyTable
WHERE 1 = 1
AND NOT EXISTS (
  SELECT *
  FROM MyTable AS t
  WHERE t.UserId = MyTable.UserId
    AND t.Date > MyTable.Date
)
;

请注意,如果用户有多行具有相同的最新 Date 值,则查询将返回所有此类条目。如有必要,您可以稍微修改子查询的条件以确保只返回一行:

  WHERE t.UserId = MyTable.UserId
    AND (t.Date > MyTable.Date
      OR t.Date = MyTable.Date AND t.RowId > MyTable.RowId
    )

在上述条件下,如果同一用户存在两行或多行具有相同Date 的行,则返回RowId 值较大的行。

【讨论】:

  • 我喜欢这个,简短易读。 +1 但是,如果有多个记录的最大日期为一个 UserID 并且 OP 只想要一行...
  • @TimSchmelter:这很好,谢谢。我将对此添加注释和解决方法。
  • 或者在子查询中我们可以使用TOP 1DateDESC顺序中的顺序,所以在这种情况下会得到最新的记录日期。
  • @Umair:我不确定我是否理解您所说的子查询,但如果您的意思是我的答案中使用的子查询,那肯定不会那样工作。 TOP n,无论有没有ORDER BY,都不会以任何方式影响 EXISTS 子查询的结果。
  • 我想添加 SELECT * FROM MyTable AS t WHERE t.UserId = MyTable.UserId AND t.Date > MyTable.Date,但是你提到的 where 查询确实对我有用。
【解决方案2】:

假设您能够修改 AND 子句中的任何内容,如果您使用的是 TSQL,则可以执行这样的查询

SELECT RowId, UserId, [Date]
FROM @myTable
WHERE 1 = 1
AND ( 
    RowId IN (
            SELECT D.RowId
            FROM (
                SELECT DISTINCT MAX(RowId) AS RowId, UserId, MAX([Date]) AS [Date]
                FROM @myTable
                GROUP BY UserId
        ) AS D
    )
)

【讨论】:

    【解决方案3】:

    试试:

    SELECT RowId, UserId, Date
    FROM MyTable
    WHERE 1 = 1
    AND EXISTS
    (SELECT 1
     FROM (SELECT UserId, MAX(Date) MaxDate
           FROM MyTable
           GROUP BY UserId) m
     WHERE m.UserId = MyTable.UserId and m.MaxDate = MyTable.Date)
    

    SQLFiddle here.

    【讨论】:

    • 如果有多个记录,其中一个 UserID 的 max-date 并且 OP 只想要一行,您如何修改此查询? sqlfiddle.com/#!6/84b97/1/0
    • @TimSchmelter:用户说“我要获取最新记录”——注意复数的使用;我理解这意味着如果同一用户的最新日期有多个记录,那么 OP 想要所有这些记录。当然,我可能是错的,在这种情况下,我需要知道是否可以使用RowId 或其他列来确定哪个是最新的;如果是这样,我将删除分组,将RowId 添加到内部查询并将MAX(Date) 更改为窗口rownumber,然后将EXISTS 连接更改为rownumber=1 和RowID -例如:sqlfiddle.com/#!6/84b97/6
    • 复数形式也是正确的,每个 UserId 有一条记录。但是,row_number 方法可以正常工作。但是如果它花费了我会删除 RowId 的第二个订单,因为你可以很容易地用 Dense_Rank 替换它以获得“多行”行为。
    【解决方案4】:

    假设RowID 是一个标识列:

    SELECT t1.RowId, t1.UserId, t1.Date
    FROM MyTable t1
    WHERE 1 = 1
    AND t1.RowID IN ( 
    
        SELECT TOP 1 t2.RowID 
        FROM MyTable t2
        WHERE  t1.UserId = t2.UserId
        AND    t2.Date = (SELECT MAX(t3.Date) FROM MyTable t3
                          WHERE t2.UserID = t3.UserId)
    
    )
    

    Demo

    【讨论】:

      猜你喜欢
      • 2020-08-12
      • 1970-01-01
      • 2018-10-07
      • 1970-01-01
      • 2020-12-22
      • 1970-01-01
      • 2021-07-03
      • 1970-01-01
      • 2019-06-23
      相关资源
      最近更新 更多