在行组中查找最小值

时间:2014-02-03 21:42:20

标签: sql sql-server tsql group-by

在SQL空间(特别是T-SQL,SQL Server 2008)中,给出以下值列表:

    Status  Date
    ------  -----------------------
    ACT     2012-01-07 11:51:06.060
    ACT     2012-01-07 11:51:07.920
    ACT     2012-01-08 04:13:29.140
    NOS     2012-01-09 04:29:16.873
    ACT     2012-01-21 12:39:37.607         <-- THIS
    ACT     2012-01-21 12:40:03.840
    ACT     2012-05-02 16:27:17.370
    GRAD    2012-05-19 13:30:02.503
    GRAD    2013-09-03 22:58:48.750

从此查询生成:

    SELECT Status, Date
    FROM Account_History
    WHERE AccountNumber = '1234'
    ORDER BY Date

此特定对象的状态在ACT开始,然后更改为NOS,然后更改为ACT,然后更改为GRAD。

从最新的&#34;组&#34;获得最短日期的最佳方法是什么?状态=&#39; ACT&#39;?

的记录

3 个答案:

答案 0 :(得分:3)

这是一个执行此操作的查询,通过识别学生状态相同的组,然后使用简单聚合:

select top 1 StudentStatus, min(WhenLastChanged) as WhenLastChanged
from (SELECT StudentStatus, WhenLastChanged,
             (row_number() over (order by "date") -
              row_number() over (partition by studentstatus order by "date)
            ) as grp
      FROM Account_History
      WHERE AccountNumber = '1234'
    ) t
where StudentStatus = 'ACT'
group by StudentStatus, grp
order by WhenLastChanged desc;

row_number()函数根据date在行组内分配序号。对于您的数据,两个row_numbers()及其区别在于:

Status  Date
------  -----------------------
ACT     2012-01-07 11:51:06.060    1      1      0
ACT     2012-01-07 11:51:07.920    2      2      0
ACT     2012-01-08 04:13:29.140    3      3      0
NOS     2012-01-09 04:29:16.873    4      1      3
ACT     2012-01-21 12:39:37.607    5      4      1
ACT     2012-01-21 12:40:03.840    6      5      1
ACT     2012-05-02 16:27:17.370    7      6      1
GRAD    2012-05-19 13:30:02.503    8      1      7
GRAD    2013-09-03 22:58:48.750    9      2      7

请注意,对于具有相同状态的行,最后一行是常量。

聚合将这些组合在一起,并选择最新的top 1 . . . order by date desc个第一个日期(min(date))。

编辑:

查询很容易调整多个帐号。我可能应该以这种方式开始,除了最后的选择比较棘手。此结果包含每个状态和帐户的日期:

select StudentStatus, min(WhenLastChanged) as WhenLastChanged
from (SELECT StudentStatus, WhenLastChanged, AccountNumber
             (row_number() over (partition by AccountNumber order by WhenLastChanged) -
              row_number() over (partition by AccountNumber, studentstatus order by WhenLastChanged)
            ) as grp
      FROM Account_History
    ) t
where StudentStatus = 'ACT'
group by AccountNumber, StudentStatus, grp
order by WhenLastChanged desc;

但是你不能轻易地获得每个帐户的最后一个。另一级子查询:

select AccountNumber, StudentStatus, WhenLastChanged
from (select AccountNumber, StudentStatus, min(WhenLastChanged) as WhenLastChanged,
             row_number() over (partition by AccountNumber, StudentStatus order by min(WhenLastChanged) desc
                               ) as seqnum
      from (SELECT AccountNumber, StudentStatus, WhenLastChanged,
                   (row_number() over (partition by AccountNumber order by WhenLastChanged) -
                    row_number() over (partition by AccountNumber, studentstatus order by WhenLastChanged)
                  ) as grp
            FROM Account_History
          ) t
      where StudentStatus = 'ACT'
      group by AccountNumber, StudentStatus, grp
     ) t
where seqnum = 1;

这使用聚合以及窗口函数row_number()。这是为组分配序列号(聚合后),每个帐户的最后日期值为1(order by min(WhenLastChanged) desc)。最外面的select然后只为每个帐户选择该行。

答案 1 :(得分:1)

SELECT [Status], MIN([Date])
FROM Table_Name
WHERE [Status] = (SELECT [Status]
                  FROM Table_Name
                  WHERE [Date] = (SELECT MAX([Date])
                                  FROM Table_Name)
                  )
GROUP BY  [Status]

在这里试试 Sql Fiddle

答案 2 :(得分:0)

  霍根:基本上,是的。我只是想知道日期/时间   帐号上次更改为ACT。以上几点后的记录   标记为这只是额外的。

我们可以寻找第一次状态更改,然后从中选择act(和max),而不只是寻找行为。

所以...每次状态改变时:

with rownumb as
(
   select *, row_number() OVER (order by date asc) as rn
)
select status, date
from rownumb A
join rownumb B on A.rn = B.rn-1
where a.status != b.status

现在找到行为项目的最大值。

with rownumb as
(
   select *, row_number() OVER (order by date asc) as rn
), statuschange as
(
  select status, date
  from rownumb A
  join rownumb B on A.rn = B.rn-1
  where a.status != b.status
)
select max(date) 
from satuschange 
where status='Act'