select tmp=0,temp=0,intime=convert(datetime,0,120) ,cardNo,tT,iDU into #T from t_ca
where tT>='2010-09-14' and tT<='2010-09-20' order by cardNo,tTdeclare @tmp int,@temp int,@biaozhi int,@name varchar(10),@tT datetime,@intime datetime
Update #T
set @tmp= case when (iDU=1) and (@biaozhi>1) and cardNo=@name then 1
else case when (iDU>1) and (@biaozhi=1) and cardNo=@name then 2 else 0 end end,
@temp = case when @tmp=1 then isnull(@temp,0)+1 else isnull(@temp,0) end,
@intime= case when (@biaozhi>1)and (iDU=1) and @name=cardNo then @tT else tT end,
@name=cardNo,@biaozhi=iDU,tmp=@tmp,temp=@temp,@tT=tT,intime=@intimeselect cardNo as 卡号,min(case when tmp=1 then intime end) as 开始时间,
max(case when tmp=2 then tT end) as 结束时间
into #1
from #T  where tmp>0  group by temp,cardNoselect convert(varchar(10),开始时间,2) as 日期,卡号,convert(varchar(20),开始时间,120) as 开始时间,
convert(varchar(20),结束时间,120) as 结束时间 from #1 where 结束时间>='2010-09-15' and 结束时间<='2010-09-16'
order by 卡号,下井时间
drop table #T,#T1,#1这个效率是不是很差?请问大哥们该如何改正?

解决方案 »

  1.   

    t_ca 表存的数据是cardNo  tT                iDU
    1       2010-09-09 08:12   1
    1       2010-09-10 08:14   1
    1       2010-09-10 08:18   2
    1       2010-09-09 05:12   2
    1       2010-09-09 08:12   1
    1       2010-09-09 03:12   1
    2       2010-09-09 08:30   1
    2       2010-09-09 12:12   2
    2       2010-09-09 03:12   1
    2       2010-09-09 08:12   2这样类似的数据。希望得到的是每个cardNo当字段iDU发生变化时的tT,当iDU从1变成2的tT和iDU从2变成1的tT.
    类似这样的卡号         开始时间               结束时间
    1          2010-09-10 08:14     2010-09-09 08:12
    2          2010-09-09 08:30     2010-09-09 03:12
    2          2010-09-09 03:12     -
      

  2.   

    这个SQL语句在查询几十万行数据的时候,显得特别慢,查询费个十几秒是经常的啊,受不了,能不能有其他方法,或者当我把查询的时期范围扩大到一个月甚至更大时,就杯具啦
      

  3.   

    网上说用到类似
    case when @tmp=1 then isnull(@temp,0)+1 else isnull(@temp,0) end
    这样的SQL语句,效率是很差的。
    还有我这个SQL用到了三个临时表,数据量大时,对他们进行插入操作效率也挺差的。怎么改进?
      

  4.   

    --> 测试数据: #tb
    if object_id('tempdb.dbo.#tb') is not null drop table #tb
    go 
    create table #tb (cardNo int,tT datetime,iDU int)
    insert into #tb
    select 1,'2010-09-09 08:12',1 union all
    select 1,'2010-09-10 08:14',1 union all
    select 1,'2010-09-10 08:18',2 union all
    select 1,'2010-09-19 05:12',2 union all
    select 1,'2010-09-19 08:12',1 union all
    select 1,'2010-09-19 13:12',1 union all
    select 2,'2010-09-09 08:30',1 union all
    select 2,'2010-09-09 12:12',2 union all
    select 2,'2010-09-09 13:12',1 union all
    select 2,'2010-09-09 18:12',2;with cte as
     (
    select px=row_number()over(order by getdate()),* from #tb

    select cardNo,
    开始时间=min(tT), 结束时间=max(tt)from cte t
    where iDU=1
     and not exists(select 1 from cte where idu=1 and cardNo=t.cardNo and px=t.px+1)
    group by cardNo
    cardNo      开始时间                    结束时间
    ----------- ----------------------- -----------------------
    1           2010-09-10 08:14:00.000 2010-09-19 13:12:00.000
    2           2010-09-09 08:30:00.000 2010-09-09 13:12:00.000(2 行受影响)
      

  5.   

    如果是sql2005以上的版本建议用
    with cte as
     代替临时表
      

  6.   

    忘了说明了,我用的是2000的数据库,没得row_number()函数啊.所以为了生成行号,用了个笨方法。
    @temp = case when @tmp=1 then isnull(@temp,0)+1 else isnull(@temp,0) end,
      

  7.   

    娘地,2000的看起来比2005功能差好多哦,这个SQL用2000写,有没得好的法子?
      

  8.   

    我这个SQL里用到了啊,数据量大时,对临时表的插入之类的操作感觉也挺费时的。
      

  9.   

    现在一般表里面一个月数据有30万行左右。查询这么多,这个SQL就杯具啦。估计用户都等不及了
      

  10.   

    这个不确定。大部分cardNo一天就有上千条,iDU的值要么是1,要么是大于1的数,排列无规律,所以为了找出开始时间和结束时间,得把每个cardNo的纪录遍历一遍。
      

  11.   

    一般我不会用Update ... case when ...else case when ... 这样容易进入死循环如果逻辑关系不严密的话...
    另外,如果你想知道每个语句执行多长时间,可以使用:
    Print convert(varchar,getdate(),121)