有个字段的值是这样的:
周三第1,2节{第4-9周};周二第1,2节{第4-9周};周四第1,2节{第4-9周};周三第1,2节{第14-19周};周四第3,4节{第4-9周};周五第1,2节{第4-9周};周二第3,4节{第4-9周};周五第3,4节{第4-9周}也可能是 周三第1,2节{第4-9周} 或
周三第1,2节{第4-9周};周二第1,2节{第4-9周}4-9 表示第四周到第九周,长度不一定想问怎么查出 15周 周三第1,2节 有课的记录用一条SQL 语句能搞定吗,不知怎么用循环?对SQL只懂一丁点点,谢谢了

解决方案 »

  1.   

    master..spt_values 表中type='p'的 number例 
      

  2.   

    create table #tb(id int,name Nvarchar(4000))
    --truncate table #tb
    insert into #tb
    select 1,'周三第1,2节{第4-9周}'
    union select 2,'周三第1,2节{第4-9周};周三第1,2节{第14-19周}'
    union select 3,'周三第1,2节{第4-9周};周二第1,2节{第4-9周};周四第1,2节{第4-9周};周三第1,2节{第14-19周}'
    union select 4,'周三第1,2节{第4-9周};周二第1,2节{第4-9周};周四第1,2节{第4-9周}'select * from #tb
    --CTE 递归找分隔字符位置法:速度极快
    with T (id,P1,P2) as
    (
        select id,charindex(';',';'+name),charindex(';',name+';')+1 from #Tb
        union all
        select a.id,b.P2,charindex(';',name+';',b.P2)+1 from #Tb a join T b on a.id=b.id where charindex(';',name+';',b.P2)>0
    )select id,name from 
    (select a.id,a.name,name1=substring(a.name+';',b.P1,b.P2-b.P1-1) from #Tb a join T b on a.id=b.id ) tt
     where charindex('周三第1,2节',name1)>0 
       and cast(substring(name1,charindex('{',name1)+2,charindex('-',name1)-charindex('{',name1)-2) as int)<=15
       and cast(substring(name1,charindex('-',name1)+1,charindex('}',name1)-charindex('-',name1)-2) as int)>=15
    order by id asc
    GO
    --注 with语句要与下面的sql语句一起执行
    id          name
    ----------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    2           周三第1,2节{第4-9周};周三第1,2节{第14-19周}
    3           周三第1,2节{第4-9周};周二第1,2节{第4-9周};周四第1,2节{第4-9周};周三第1,2节{第14-19周}(2 行受影响)
      

  3.   

    declare @wk int --第几周
    declare @i  int --第几节课
    set @wk=15 --第15周
    set @i=2  --第2节
    ;with T (id,P1,P2) as
    (
        select id,charindex(';',';'+name),charindex(';',name+';')+1 from #Tb
        union all
        select a.id,b.P2,charindex(';',name+';',b.P2)+1 from #Tb a join T b on a.id=b.id where charindex(';',name+';',b.P2)>0
    )
    --这里p1,是保存字符串分隔;词的起始位置
    --p2,是结束位置,注意前头加;,结尾加;
    --select a.id,name1=substring(a.name+';',b.P1,b.P2-b.P1-1) from #Tb a join T b on a.id=b.id
    --这里就得到切割后的表,可放入临时表中
    select id,name1,name from 
    (select a.id,a.name,name1=substring(a.name+';',b.P1,b.P2-b.P1-1) from #Tb a join T b on a.id=b.id ) tt
     where 
       (charindex('第'+cast(@i as varchar(2))+',',name1)>0 or charindex(','+cast(@i as varchar(2))+'节',name1)>0 )
       and cast(substring(name1,charindex('{',name1)+2,charindex('-',name1)-charindex('{',name1)-2) as int)<=@wk
       and cast(substring(name1,charindex('-',name1)+1,charindex('}',name1)-charindex('-',name1)-2) as int)>=@wk
    order by id asc
      

  4.   

    select id,name from 
    (select a.id,a.name,name1=substring(a.name+';',b.P1,b.P2-b.P1-1) from 
     (
      select * from #tb
      with T (id,P1,P2) as
      (
        select id,charindex(';',';'+name),charindex(';',name+';')+1 from #Tb
        union all
        select a.id,b.P2,charindex(';',name+';',b.P2)+1 from #Tb a join T b on a.id=b.id where charindex(';',name+';',b.P2)>0
      )
      )a join T b on a.id=b.id ) tt
     where charindex('周三第1,2节',name1)>0 
       and cast(substring(name1,charindex('{',name1)+2,charindex('-',name1)-charindex('{',name1)-2) as int)<=15
       and cast(substring(name1,charindex('-',name1)+1,charindex('}',name1)-charindex('-',name1)-2) as int)>=15
    order by id asc能不能把前一个放在第二个中间,我没办法测试,因为我对 SQL只懂点皮毛,想问的可能是最基本的SQL,听说你这是用的 SQL SERVER
      

  5.   

    非常感谢abuying,通过学习、抄袭、修改,及在同事CXL帮助修改后,终于可以在一条语句中完成了。虽然没有对abuying提供的语句弄明白,但有些思路提供了极大的帮助,再次感谢我的主要是想在一条语句中完成,想看看SQL能否在一条语句中完成循环(这样是循环吗,我认为是循环提取)的感觉还有很多疑问,如level的用法,递归(如abuying提供)在SQL中是怎么完成的,会在再在其他帖中提出,希望各位指教。以下语句,用的2楼的表,不过表名改为t_temp,查"第15周周三第1,2节" 的记录,在oracle中测试正确
    select id,name,new_name from 
    (select a.id,a.name,b.new_name from t_temp a join 
    (select distinct id,substr(name,instr(name,';',1,level)+1,instr(name,';',1,level+1)-instr(name,';',1,level)-1) as new_name
     from (select id,';'||name||';' name from t_temp)   
    connect by level<=length(name)-length(replace(name,';',''))-1) b on a.id=b.id) tt
     where 
       (instr(new_name,'周三第1,2')>0)
    and to_number(substr(new_name,instr(new_name,'第',1,2)+1,instr(new_name,'-')-instr(new_name,'第',1,2)-1))<=15  
     and to_number(substr(new_name,instr(new_name,'-')+1,instr(new_name,'周',1,2)-instr(new_name,'-')-1))>=15
      

  6.   

    进一步简化,但数据量比较大时,没有结果,约近一千条时,不知是怎么了?
    select distinct id,name,new_name from 
    (select distinct id,name,
     substr(name,instr(name,';',1,level)+1,instr(name,';',1,level+1)-instr(name,';',1,level)-1) as new_name
     from (select id,';'||name||';' name from t_temp)   
    connect by level<=length(name)-length(replace(name,';',''))-1)
     where 
       instr(new_name,'周三第1,2')>0
     and to_number(substr(new_name,instr(new_name,'第',1,2)+1,instr(new_name,'-')-instr(new_name,'第',1,2)-1))<=15  
     and to_number(substr(new_name,instr(new_name,'-')+1,instr(new_name,'周',1,2)-instr(new_name,'-')-1))>=15