2015-04-16 90 views
6

我有表,这样的结构简化SQL SELECT语句

CREATE TABLE UsersHistory 
(
    Id   INT IDENTITY, 
    UserID  INT, 
    StatusId INT, 
    CreateTime DATETIME, 
    ChangedTime DATETIME 
) 

INSERT INTO UsersHistory(UserID, StatusId, CreateTime, ChangedTime) 
SELECT 1,1,'20150414','20150414' UNION ALL 
SELECT 1,2,'20150414','20150415' UNION ALL 
SELECT 1,3,'20150414','20150416' UNION ALL 
SELECT 2,1,'20150413','20150413' UNION ALL 
SELECT 2,3,'20150413','20150416' 

和查询

;WITH k AS (
SELECT uh.UserID,MAX(uh.ChangedTime) AS Dt FROM UsersHistory AS uh 
WHERE uh.ChangedTime<'20150416' 
GROUP BY uh.UserID 
) 
SELECT k.UserID,uh.StatusId FROM k 
INNER JOIN UsersHistory AS uh 
    ON k.UserID = uh.UserID AND k.Dt = uh.ChangedTime 

查询是太容易,而不是需要更多的解释。我想简化它。 (删除加入日期时间类型列)。

有何建议?

回答

1

您可以使用ROW_NUMBER()PARTITION实现这一目标。像这样的东西

;WITH CTE as 
( 
    SELECT UserID, StatusId, CreateTime, ChangedTime,ROW_NUMBER()OVER(PARTITION BY UserID ORDER BY ChangedTime DESC) r 
    FROM UsersHistory 
    WHERE ChangedTime < '20150416' 
) 
SELECT UserID, StatusId FROM CTE 
WHERE r = 1 
+1

这是当然的赢家。非常复杂的问题有时会导致非常复杂的答案。在这种情况下看到简单是一个很好的天赋。 –

0

在SQL Server 2012+,你可以使用first_value()

SELECT uh.UserID, 
     FIRST_VALUE(uh.StatusId) OVER (PARTITION BY uh.UserId ORDER BY ChangedTIme DESC) 
     MAX(uh.ChangedTime) AS Dt 
FROM UsersHistory AS uh 
WHERE uh.ChangedTime < '20150416'; 
0

据我了解,你想与其中ChangedTime不等于“20150416”的最大ChangedTime选择记录的用户名和StatusId。请尝试此查询:

SELECT 
    uh.UserId, uh.StatusId 
    FROM UsersHistory AS uh 
    WHERE uh.ChangedTime<'20150416' 
    AND uh.ChangedTime=(SELECT MAX(ChangedTime) FROM UsersHistory 
              WHERE UserId=uh.UserId); 
0

您可以在WHERE子句中添加子查询。类似的东西:

SELECT uh.UserID, 
     MAX(uh.ChangedTime) AS Dt, 
     uh.StatusId 
FROM UsersHistory uh 
WHERE uh.ChangedTime < '20150416' 
     AND uh.ChangedTime= 
         (
         SELECT MAX(ChangedTime) 
         FROM UsersHistory 
         WHERE UserId=uh.UserId 
         ) 
GROUP BY uh.UserID, uh.StatusId 
+0

您正在按用户名进行分组,并且您选择了状态缺席聚合。这是语法错误。 –

+0

谢谢你纠正,错过了,修正了。 –

0

随着APPLY

Select uh1.UserID, oa.StatusID 
From UserHistory uh1 
Cross Apply(Select * From (Select Top 1 uh2.StatusID, uh2.Changetime 
      From UserHistory uh2 
      Where uh2.UserID = uh1.UserID And uh2.Changetime < '20150416' 
      Order By uh2.Changetime desc) t where t.Changetime = uh1.Changetime) oa 
0
SELECT 
    distinct uh.UserID, 
    statusid 
FROM UsersHistory uh 
inner join 
    (select 
     UserID, 
     max(ChangedTime) dt 
    from UsersHistory 
    group by UserID) ct 
on (ct.UserID=uh.userid and ct.dt=uh.ChangedTime)