仅当行在ON和OFF的描述中时才列出行

时间:2015-10-30 13:38:02

标签: sql sql-server sql-server-2008

我有一个包含以下字段的表,我需要一个视图/查询,它将为表中的每个帐户列出第一行开头的行 Descr = ON TEST(如果存在)" THRU"描述=关闭测试。

它需要列出中间的所有行,但忽略所有其他行。

提前致谢。

account      date                descr
1234      10/05/15 17:45:23      MISC
1234      10/05/15 17:45:24      ON TEST
1234      10/05/15 17:51:32      DOOR
1234      10/05/15 17:52:52      CLOSE
1234      10/05/15 17:55:08      OPEN
1234      10/05/15 17:56:56      CLOSE
1234      10/05/15 18:08:16      OPEN
1234      10/05/15 18:10:28      CLOSE
1234      10/05/15 18:10:32      CLOSE
1234      10/05/15 18:15:02      OFF TEST
1234      10/05/15 19:10:32      CLOSE

期望的结果::

1234      10/05/15 17:45:24      ON TEST
1234      10/05/15 17:51:32      DOOR
1234      10/05/15 17:52:52      CLOSE
1234      10/05/15 17:55:08      OPEN
1234      10/05/15 17:56:56      CLOSE
1234      10/05/15 18:08:16      OPEN
1234      10/05/15 18:10:28      CLOSE
1234      10/05/15 18:10:32      CLOSE
1234      10/05/15 18:15:02      OFF TEST

4 个答案:

答案 0 :(得分:2)

在一般情况下获取开/关日期有点棘手。这符合你的规则,应该得到日期。

select t.account, ton.on_date,
       min(case when t.date >= ton.on_date) as off_date
from t join
     (select account, min(date) as on_date
      from t
      where t.descr = 'ON TEST'
      group by account
     ) ton
     on t.account = ton.account
where t.descr = 'OFF TEST'
group by t.account, ton.on_date;

获取原始行:

with onoff as (
      select t.account, ton.on_date,
             min(case when t.date >= ton.on_date) as off_date
      from t join
           (select account, min(date) as on_date
            from t
            where t.descr = 'ON TEST'
            group by account
           ) ton
           on t.account = ton.account
      where t.descr = 'OFF TEST'
      group by t.account, ton.on_date
     )
select t.*
from t join
     onoff
     on t.account = onoff.account
where t.date between onoff.on_date and onoff.off_date;

如果你认为在第一个" on"之前没有" off"则问题会简单得多。例如:

      select t.*
      from t join
           (select account,
                   min(case when t.descr = 'ON TEST' then date end) as on_date,
                   min(case when t.descr = 'OFF TEST' then date end) as off_date
            from t
            group by account
           ) onoff
           on t.account = ton.account
       where t.date between onoff.on_date and onoff.off_date;

答案 1 :(得分:1)

双重自我加入,一个用于开始和停止:

select t.account, t.date, t.descr
from tablename t
join tablename tstart on t.account = tstart.account
                     and tstart.descr = 'ON TEST'
join tablename tstop  on t.account = tstop.account
                     and tstop.descr = 'OFF TEST'
where t.date between tstart.date and tstop.date

或者,加倍EXISTS

select t.account, t.date, t.descr
from tablename t
where exists (select 1 from tablename tstart
              where t.account = tstart.account
                and tstart.descr = 'ON TEST'
                and t.date >= tstart.date)
  and exists (select 1 from tablename tstop
              where t.account = tstop.account
                and tstop.descr = 'ON TEST'
                and t.date <= tstop.date)

答案 2 :(得分:0)

选择ON TEST date和OFF TEST date之间的所有行。

select *
from table_name
where date >= (select date from table_name where descr = 'ON TEST')
and date <= (select date from table_name where descr = 'OFF TEST')
order by date asc

答案 3 :(得分:0)

您需要比较'ON TEST'和'OFF TEST'的最新时间戳,并检查'​​ON'是否大于'OFF':

SELECT *
FROM
 ( SELECT t.*,
      (SELECT MAX(date) -- most recent 'ON TEST'
       FROM tab AS t2
       WHERE t2.account = t.account
         AND t2.date <= t.date
         AND t2.descr = 'ON TEST') AS last_on,
      (SELECT MAX(date) -- most recent 'OFF TEST'
       FROM tab AS t2
       WHERE t2.account = t.account
         AND t2.date <  t.date
         AND t2.descr = 'OFF TEST') AS last_off
   FROM tab AS t
 ) AS dt
WHERE last_on >= COALESCE(last_off, last_on) -- 'ON' > 'OFF' or no previous 'OFF'

在SQL Server 2012中,使用OVER会更容易,例如

MAX(CASE WHEN descr = 'ON TEST' THEN date END)
OVER (PARTITION BY account
      ORDER BY date
      ROWS UNBOUNDED PRECEDING) AS last_on