如何根据日期字段选择不同的数据?

时间:2011-05-25 21:35:31

标签: sql tsql select group-by greatest-n-per-group

我有一个表,用于存储另一个表中对象的更改日志。这是我的表格内容:

ObjID   Color   Date                     User
------- ------- ------------------------ --------
1       Red     2010-01-01 12:22:00.000  Joe
1       Blue    2010-01-02 15:22:00.000  Jill
1       Green   2010-01-03 16:22:00.000  Joe
1       White   2010-01-10 09:22:00.000  Mike
2       Red     2010-01-09 10:22:00.000  Mike
2       Blue    2010-01-12 09:22:00.000  Jill
2       Orange  2010-01-12 15:22:00.000  Joe

我想为每个对象选择最近的日期,以及该记录日期的颜色和用户。

基本上,我想要这个结果集:

ObjID   Color   Date                     User
------- ------- ------------------------ --------
1       White   2010-01-10 09:22:00.000  Mike
2       Orange  2010-01-12 15:22:00.000  Joe

我无法绕过我需要编写的SQL查询以获取此数据...

我正在通过ODBC从iSeries DB2数据库(AS / 400)中检索数据。

7 个答案:

答案 0 :(得分:4)

嘿那里,我想你想要以下(ColorTable是你的表名):

SELECT Color.* 
FROM ColorTable as Color
INNER JOIN 
(
SELECT ObjID, MAX(Date) as Date
FROM ColorTable
GROUP BY ObjID
) as MaxDateByColor
ON Color.ObjID = MaxDateByColor.ObjID
AND Color.Date = MaxDateByColor.Date 

答案 1 :(得分:3)

至少假设SQL Server 2005

DECLARE @T TABLE (ObjID INT,Color VARCHAR(10),[Date] DATETIME,[User] VARCHAR(50))

INSERT INTO @T
SELECT 1,'Red',' 2010-01-01 12:22:00.000','Joe' UNION ALL
SELECT 1,'Blue','2010-01-02 15:22:00.000','Jill' UNION ALL
SELECT 1,'Green',' 2010-01-03 16:22:00.000','Joe' UNION ALL
SELECT 1,'White',' 2010-01-10 09:22:00.000','Mike' UNION ALL
SELECT 2,'Red',' 2010-01-09 10:22:00.000','Mike' UNION ALL
SELECT 2,'Blue','2010-01-12 09:22:00.000','Jill' UNION ALL
SELECT 2,'Orange','2010-01-12 15:22:00.000','Joe'

;WITH T AS
(
SELECT *,
       ROW_NUMBER() OVER (PARTITION BY ObjID ORDER BY Date DESC) AS RN
FROM @T
)
SELECT ObjID,
       Color,
       [Date],
       [User]
FROM T 
WHERE RN=1

或者来自评论链接到文章的SQL Server 2000方法

SELECT ObjID,
  CAST(SUBSTRING(string, 24, 33) AS VARCHAR(10)) AS Color,
  CAST(SUBSTRING(string,  1, 23) AS DATETIME ) AS [Date],
  CAST(SUBSTRING(string, 34, 83) AS  VARCHAR(50)) AS [User]
FROM 
(
SELECT ObjID, 
          MAX((CONVERT(CHAR(23), [Date], 126)
         + CAST(Color AS CHAR(10))
         + CAST([User] AS CHAR(50))) COLLATE Latin1_General_BIN) AS string
FROM @T
GROUP BY ObjID) T;

答案 2 :(得分:1)

如果你有一个Objects表,而你的ObjectHistory表有一个ObjID和date的索引,那么这可能比目前给出的其他查询表现更好:

SELECT
   X.*
FROM
   Objects O
   CROSS APPLY (
      SELECT TOP 1 *
      FROM ObjectHistory H
      WHERE O.ObjID = O.ObjID
      ORDER BY H.[Date] DESC
   ) X

只有当您从Objects表中提取列时,性能改进才会出现,但它值得一试。

如果您想要所有对象,无论他们是否有历史记录条目,请切换到OUTER APPLY(当然使用O.ObjID代替H.ObjID)。

这个查询的巧妙之处在于

  1. 它解决了Date值可能有重复的情况
  2. 它可以支持每组任意数量的项目(例如,前5名而不是前1名)

答案 3 :(得分:0)

答案 4 :(得分:0)

SELECT t1.* FROM Table_name as t1
INNER JOIN (
  SELECT MAX(Date) as MaxDate, ObjID FROM Table_name
  GROUP BY ObjID
) as t2
ON t1.ObjID = t2.ObjID AND t1.Date = t2.MaxDate

答案 5 :(得分:0)

你可以找出每个对象最近的变化:

        select objectid, max(changedate) as LatestChange
        from LOG
        group by objectid

然后,您可以通过将上面返回的集合(实例化为已被赋予别名的内联视图)链接到同一个表来获取颜色和用户列:

       select color, user, FOO.objectid, FOO.LatestChange
       from LOG
       inner join
       (

          select objectid, max(changedate) as LatestChange
        from LOG
        group by objectid


        ) as FOO
        on LOG.objectid = FOO.objectid and LOG.changedate = FOO.LatestChange

答案 6 :(得分:0)

像上面的马丁史密斯一样, 只需在分区上执行行号并选择最近的一行 像

SELECT  Color,Date,User
FROM (
   SELECT *,
          ROW_NUMBER() OVER (PARTITION BY User ORDER BY [DATE]) AS ROW_NUMBER
   FROM [tablename]
   ) AS ROWS
WHERE 
ROW_NUMBER = 2