2015-04-16 120 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)