简化SQL select语句

时间:2015-04-16 10:16:12

标签: sql tsql

我有这种结构的表

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

查询太简单了,不需要更多解释。我想简化我的。 (删除与datetime类型列的连接)。

有任何建议吗?

6 个答案:

答案 0 :(得分: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';

答案 2 :(得分:0)

据我所知,您希望选择具有最大ChangedTime的记录的UserId和StatusId,其中ChangedTime不等于&#39; 20150416&#39;。请尝试此查询:

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);

答案 3 :(得分: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 

答案 4 :(得分: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

答案 5 :(得分: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)