选择日期后选择最小日期

时间:2013-06-24 17:29:25

标签: sql sql-server-2012

我的架构看起来像这样:

------------------------------------
ID | Time | Type | Description | obj
------------------------------------

有些数据会像

1 | 01/01/1900 01:01:01 AM | 1 | Start | O1
2 | 01/01/1900 01:01:02 AM | 1 | Start | O2
3 | 01/01/1900 01:01:03 AM | 2 | Stop  | O1
4 | 01/01/1900 01:01:04 AM | 2 | Stop  | O2

注意:

  • O1,O2等是进程操作的对象的ID。它在开始/停止时间之间是一致的,但每个对象将有多个开始/停止时间(该过程将多次开始和完成对特定对象的操作,并且我的查询将需要为每次选择记录进程处理该对象)
  • 描述说开始/停止是为了这个问题的清晰度。在实践中,它具有解析出的各种数据。

所以,我需要的是彼此最接近的开始时间和停止时间对。换句话说:对于每个开始时间,我需要下一个最接近的停止时间。因此,上面的示例数据的select语句的结果(仅选择的id)将返回:

  

(1,3)

     

(2,4)

我尝试了什么:

SELECT  obj, 
        [Time] AS StartTime, 
        (SELECT MIN([TIME]) AS t
         FROM   TheTable
         WHERE  [Type] = 2
         HAVING MIN([Time]) > StartTime) AS StopTime
FROM     TheTable
WHERE    [Type] = 1;

这显然不起作用,因为内部选择未知StartTime。 如果没有内部选择中的Having子句,它会运行但我会为所有条目获得相同的StopTime,正如您所期望的那样。当然,这不是我需要的。

有什么方法可以解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

SELECT t1.obj, t1.Time as Start, min(t2.Time) as Stop
FROM TheTable t1
LEFT OUTER JOIN TheTable t2
ON t1.obj = t2.obj and t2.Description = 'Stop' and t2.Time > t1.time
WHERE t1.Description = 'Start' 
GROUP BY (t1.obj, t1.Time, t1.Description, t2.Description)

左外连接,因为可能有一个开始时间而不是停止时间

答案 1 :(得分:1)

我不确定为什么它不起作用。

你总是可以在SubQ中使用外部列引用,你缺少'逗号'和'分组'BTW

SELECT  obj, 
       [Time] AS StartTime,
       (SELECT MIN([TIME]) AS t
         FROM   TheTable
         WHERE  [Type] = 2
         and t1.obj = obj
         HAVING t > StartTime) AS StopTime
FROM     TheTable t1
WHERE    [Type] = 1
group by obj,TIME;

编辑:

我不是SQL服务器的专家,也不知道为什么列别名不起作用。此查询适用于我正在使用的其他Dbs,如Teradata。无论如何,您可以使用表别名来解决此问题。

SELECT  obj, 
   [TIME] AS StartTime,
   (SELECT MIN([TIME]) As [tt]
     FROM   TheTable
     WHERE  [Type] = 2
    and t1.obj = obj
     HAVING MIN([TIME]) > t1.TIME
      ) AS StopTime
FROM     TheTable t1
WHERE    [Type] = 1
group by obj,TIME;

SQLFiddle:

http://sqlfiddle.com/#!6/3a745/14

现在,似乎SQL服务器中的Having子句中不允许使用列别名:

SELECT  obj, 
   min([tdate]) AS StartTime from thetable group by obj having starttime>5 ;

无效的列名'starttime'。:SELECT obj,min([tdate])来自thetable group的AS StartTime by obj having starttime> 5