【问题标题】:Order By Minimum distance from getdate按与 getdate 的最小距离排序
【发布时间】:2013-01-23 10:37:18
【问题描述】:

我有这张桌子

Id_User Id_Subscription Date_Expiration
1       1               2013-01-21
1       2               2013-01-28    
2       1               2013-01-15
2       2               2013-01-30
2       3               2013-01-31

我想按距离 desc 对距 getdate 最小距离的用户进行排序(无论 Id_Subscription 是多少)。示例:

Position Id_User   Distance in day
1        2         7
2        1         2

我已经尝试过这样做

SELECT  ROW_NUMBER() OVER(ORDER BY COALESCE(MIN(us.Date_Expiration), 
CAST('2015-01-29 16:30:23.000' AS DATE)) DESC, us.id_user) AS Row, us.id_user
FROM User_Subscription us
GROUP BY a.Id_Anagrafica

但它不正确。

【问题讨论】:

  • 我猜表的最后两行是重复的?或者他们是必需的?
  • 这是一个错误,我已经纠正了
  • 我认为 userId (2) 最大距离应该是 8,我不确定你是如何得到 userId(1) 最大距离 2。我认为应该是 5?
  • 对不起,我犯了错误。我想要从 Date_Expiration 的最小距离按距离 desc 排序

标签: sql date sql-order-by date-range


【解决方案1】:

您可以将ABSDatediff 一起使用,例如:

SELECT Row_number() 
         OVER( 
           ORDER BY Abs(Datediff(dd, Getdate(), Date_Expiration)) ASC, 
         us.id_user) AS Row, 
       us.id_user 
FROM   user_subscription us 

完成您的问题。我假设您想要每个用户的最大距离(以天为单位)。因此,您可以在OVER 子句中使用PARTION BY,例如(未测试,SQL-Server >= 2005):

WITH cte 
     AS (SELECT Position = Row_number() 
                             OVER( 
                               partition BY id_user 
                               ORDER BY Abs(Datediff(dd, Getdate(), 
                             date_expiration ) 
                             ) 
                             DESC), 
                id_user, 
                [Distance in day] = Abs(Datediff(dd, Getdate(), date_expiration) 
                                    ) 
         FROM   user_subscription) 
SELECT position, 
       id_user, 
       [distance in day] AS [Max Distance in day] 
FROM   cte 
WHERE  position = 1 

DEMO

【讨论】:

  • WHERE position =1 是什么意思?
  • @LuigiSaggese:这是自ORDER BY Abs(Datediff(dd, Getdate(), date_expiration)) DESC以来与GetDate的最大距离的每个用户的记录。
  • 对不起,我犯了错误。我想要从 Date_Expiration 的最小距离按距离 desc 排序
  • 这里是sql fiddle。我认为它不起作用。
  • @Kaf:谢谢,我错过了CTE 中选择中的FROM 子句;)编辑了我的答案并添加了sql-fiddle。
【解决方案2】:

具有如下表结构

create table user1(id_user number,id_sub number,date_exp date);

试试这个:

select row_number()   OVER (ORDER BY user1.id_user) position,id_user,MAX(date_exp)-MIN(date_exp) Max_Distance_in_day from user1 group by id_user;

带输出:

| POSITION | ID_USER | MAX_DISTANCE_IN_DAY |
--------------------------------------------
|        1 |       1 |                   7 |
|        2 |       2 |                  16 |

这里是fiddle link

【讨论】:

  • 对不起,我犯了错误。我想从 Date_Expiration 的最小距离按距离 desc 排序
【解决方案3】:

试试这个查询。这里是Sql-fiddle example

select row_number() over(order by numberofdays desc) position, 
           Id_User, numberofdays 
from (
     select Id_User, abs(datediff(day, getdate(), Date_Expiration )) numberofdays,
            rank() over (partition by Id_User order by abs(datediff(day, getdate(),  Date_Expiration )) ) rnk
     from user_subscription
    ) A
where rnk = 1


--Results
POSITION    ID_USER NUMBEROFDAYS
1           2        7
2           1        2

【讨论】:

  • 对不起,我犯了错误。我想按距离 desc 与 Date_Expiration 的最小距离。检查你的答案。
  • @LuigiSaggese:好的排序。它提供了你现在需要的东西。
【解决方案4】:
select 
       ROW_NUMBER() over (order by min(abs(datediff(d,date_expiration,getdate()))) desc) [rank]
       ,id_user
       ,min(abs(datediff(d,date_expiration,getdate()))) as distance
from User_Subscription
group by id_user`

【讨论】: