SQL Server根据日期时间和用户类型选择记录

时间:2016-07-28 08:19:41

标签: sql-server

     id|   type   |  datetime    |
    ---| ---------|--------------|
     1 | admin    | 2016-01-03   |
     2 | user     | 2016-01-07   |
     3 | user     | 2016-01-08   |
     4 | admin    | 2016-01-04   |
     5 | user     | 2016-01-01   |
     6 | user     | 2016-01-03   |
     7 | user     | 2016-01-05   |
     8 | user     | 2016-01-09   |

假设我上面有一张桌子,我需要根据日期时间重新排列。第一条记录必须来自admin,并且只有admin类型的最新日期时间。然后第二到第五条记录必须从用户类型中按日期时间降序排序。然后,第六条记录必须来自具有第二个最新日期时间的管理员类型。查询的预期结果如下表所示。

预期结果:

     id|   type   |  datetime    |
    ---| ---------|--------------|
     4 | admin    | 2016-01-04   |
     8 | user     | 2016-01-09   |
     3 | user     | 2016-01-08   |        
     2 | user     | 2016-01-07   |
     1 | admin    | 2016-01-03   |
     7 | user     | 2016-01-05   |
     6 | user     | 2016-01-03   |
     5 | user     | 2016-01-01   |

你们能告诉我如何编写查询以获得预期的结果吗?

2 个答案:

答案 0 :(得分:3)

您可以在下面的示例中使用NTILE,它将行分为2组,然后您只需按组编号和日期时间对其进行排序:

SELECT  id,
        [type],
        [datetime]
FROM (
    SELECT  id,
            [type],
            [datetime],
            NTILE(2) OVER (ORDER BY [datetime] DESC) as NT
    FROM YourTable
    WHERE [type] = 'admin' 
    UNION ALL
    SELECT  id,
            [type],
            [datetime],
            NTILE(2) OVER (ORDER BY [datetime] DESC) as NT
    FROM YourTable
    WHERE [type] = 'user'
    ) as p
ORDER BY NT, [type]

输出:

id  type    datetime
4   admin   2016-01-04
8   user    2016-01-09
3   user    2016-01-08
2   user    2016-01-07
1   admin   2016-01-03
7   user    2016-01-05
6   user    2016-01-03
5   user    2016-01-01

注意:如果您需要动态确定组号(f.e.基于行数),您可以使用:

DECLARE @i int

SELECT @i = --some number

NTILE(@i) OVER (ORDER BY ...

我建议使用:

SELECT @i = CAST(CASE WHEN COUNT(*)%4.00 = 1 THEN ROUND(COUNT(*)/4.00,0)+1 ELSE ROUND(COUNT(*)/4.00,0) END as int)
FROM YourTable

答案 1 :(得分:3)

如果您的计数不能完全被您想要分组的用户数量整除,我找到了一种方法,可以在没有NTILE问题的情况下执行此操作。基于gofr1的脚本,我建议你使用它:

SELECT  id,
        [type],
        [datetime]
FROM (
    SELECT  id,
            [type],
            [datetime],
            ROW_NUMBER() OVER (ORDER BY [datetime]) - 1 Idx
    FROM YourTable
    WHERE [type] = 'admin'
    UNION ALL
    SELECT  id,
            [type],
            [datetime],
            FLOOR((ROW_NUMBER() OVER (ORDER BY [datetime]) - 1) / 3) Idx
    FROM YourTable
    WHERE [type] = 'user'
    ) as p
ORDER BY Idx, [type]