我做了一个旅游报名程序,以下是报名表(Regist) 
-- fid为所带家属的id字符串,
--route为选择的线路id | fid | route1  |1,2 | A 
2  |3,4 | B
3  |5,6 | A家属表 family
--子女收集身高信息,父母收集年龄。id 与Regist.fid关联
id | relation | height | age1  |子女      | 120 |null
2  |父亲      | null|60   
3  |子女      | 110 |null
4  |父亲      | null|65
5  |子女      | 110 |null
6  |父亲      | null|65 有一个用来设置统计结果的表。
--toplimit上限,downlimit下限
--对子女来说是身高,对父亲来说是年龄,这些纪录是动态添加的relation |toplimit | downlimit子女     |100 | 110
子女     |111 | 120
子女     |121 | 130
父亲      |50 | 60 
父亲      |61 | 70
===》要求的统计人数结果               子女(身高)        父亲年龄
线路 | 100-110 |111-120| 121-130| 50-60|61-70
---------------------------------------------- 
A|1|1|0|1|1B|1|0|0|0|1这个该如何实现?      

解决方案 »

  1.   

    --> 测试数据:#1
    if object_id('tempdb.dbo.#1') is not null drop table #1
    create table #1(id int, fid varchar(8), route varchar(8))
    insert into #1
    select 1, '1,2', 'A' union all
    select 2, '3,4', 'B' union all
    select 3, '5,6', 'A'
    --> 测试数据:#2
    if object_id('tempdb.dbo.#2') is not null drop table #2
    create table #2(id int, relation varchar(8), height int, age int)
    insert into #2
    select 1, '子女', 120, null union all
    select 2, '父亲', null, 60 union all
    select 3, '子女', 110, null union all
    select 4, '父亲', null, 65 union all
    select 5, '子女', 110, null union all
    select 6, '父亲', null, 65
    --> 测试数据:#3
    if object_id('tempdb.dbo.#3') is not null drop table #3
    create table #3(relation varchar(8), toplimit int, downlimit int)
    insert into #3
    select '子女', 100, 110 union all
    select '子女', 111, 120 union all
    select '子女', 121, 130 union all
    select '父亲', 50, 60 union all
    select '父亲', 61, 70--> case when
    select a.route,
    [100-110] = sum(case when c.toplimit=100 and c.downlimit=110 then 1 else 0 end),
    [111-120] = sum(case when c.toplimit=111 and c.downlimit=120 then 1 else 0 end),
    [121-130] = sum(case when c.toplimit=121 and c.downlimit=130 then 1 else 0 end),
    [50-60] = sum(case when c.toplimit=50 and c.downlimit=60 then 1 else 0 end),
    [61-70] = sum(case when c.toplimit=61 and c.downlimit=70 then 1 else 0 end)
    from #1 a, #2 b, #3 c
    where ','+a.fid+',' like '%,'+ltrim(b.id)+',%'
    and b.relation=c.relation and isnull(b.height,b.age) between c.toplimit and c.downlimit
    group by a.route/*
    route    100-110     111-120     121-130     50-60       61-70
    -------- ----------- ----------- ----------- ----------- -----------
    A        1           1           0           1           1
    B        1           0           0           0           1
    */--> 2005/pivot
    select
    route, [100-110], [111-120], [121-130], [50-60], [61-70]
    from
    (
    select a.route, ltrim(c.toplimit)+'-'+ltrim(c.downlimit)r from #1 a, #2 b, #3 c
    where ','+a.fid+',' like '%,'+ltrim(b.id)+',%'
    and b.relation=c.relation and isnull(b.height,b.age) between c.toplimit and c.downlimit
    ) t
    pivot
    (
    count(r) for r in ([100-110], [111-120], [121-130], [50-60], [61-70])
    ) p/*
    route    100-110     111-120     121-130     50-60       61-70
    -------- ----------- ----------- ----------- ----------- -----------
    A        1           1           0           1           1
    B        1           0           0           0           1
    */
      

  2.   

    顺便说一下,最好能用sql2000的语法,
      

  3.   

    --如果是动态的,则使用
    declare @sql varchar(8000)
     set @sql='select a.route'
     select @sql=@sql +',sum(case when c.toplimit='+ltrim(toplimit)+' and c.downlimit='+ltrim(downlimit)+' then 1 else 0 end )as ['+ltrim(toplimit)+'-'+ltrim(downlimit)+']'
     from (select toplimit,downlimit from #3) m
    --print @sql
     set @sql=@sql+'from #1 a, #2 b, #3 c
    where '+''',''+'+'a.fid'+'+'','''+' like '+'''%,''+'+'ltrim(b.id)'+'+'',%'''+'
    and b.relation=c.relation and isnull(b.height,b.age) between c.toplimit and c.downlimit
    group by a.route'
    print @sql
    exec(@sql)
    route    100-110     111-120     121-130     50-60       61-70
    -------- ----------- ----------- ----------- ----------- -----------
    A        1           1           0           1           1
    B        1           0           0           0           1(2 行受影响)
      

  4.   


    create table Regist
    ( [id] int,
      [fid] varchar(100),
      [route] varchar(10)
    )create table Family
    ( [id] int,
      [relation] varchar(100),
      [hegiht] int,
      [age] int
    )create table Relation_limit
    ( relation varchar(100),
      toplimit varchar(10),
      downlimit varchar(10)
    )insert into Regist
    select 1,'1,2','A' union all
    select 2,'3,4','B' union all
    select 3,'5,6','A' insert into Family
    select 1,'子女',120,null union all
    select 2,'父亲',null,60 union all
    select 3,'子女',110,null union all
    select 4,'父亲',null,65 union all
    select 5,'子女',110,null union all
    select 6,'父亲',null,65 insert into Relation_limit
    select '子女',100,110 union all
    select '子女',111,120 union all
    select '子女',121,130 union all
    select '父亲',50,60 union all
    select '父亲',61,70 
      

  5.   


    if exists( select 1 from sys.objects where name = 'relation_pivot')
    begin
        drop table relation_pivot
    end
    select b.route,
           case when a.relation='父亲'
                  then '父亲(年龄)'+' '+a.toplimit+'-'+a.downlimit
                when a.relation='子女'
                  then '子女(身高)'+' '+a.toplimit+'-'+a.downlimit
           end as relation,
           count(b.fid) as person_num
    into   relation_pivot
    from   Relation_limit a
           left outer join (
    select a.route,a.fid,b.relation,isnull(b.hegiht,b.age) as val
    from (
    select a.id,
       substring(a.fid,b.number,charindex(',',a.fid+',',b.number+1)-b.number) as fid,
       a.route
    from   Regist a
       inner join master.dbo.spt_values b
     on substring(','+a.fid,b.number,1) = ','
    where  b.type = 'P' and b.number > 0
     ) a
     inner join Family b
       on a.fid = b.id
                           ) b
             on a.relation = b.relation 
                and b.val between a.toplimit and a.downlimit 
    where  b.route is not null
    group by b.route,
             case when a.relation='父亲'
                    then '父亲(年龄)'+' '+a.toplimit+'-'+a.downlimit
                  when a.relation='子女'
                    then '子女(身高)'+' '+a.toplimit+'-'+a.downlimit
             end declare @pivot_name varchar(500),@select_name varchar(500)
    select @pivot_name = '',@select_name = 'route,'select @pivot_name = @pivot_name+'['+relation+'],',
           @select_name = @select_name + 'isnull([' + relation + '],0) as [' + relation + '],'
    from ( select distinct
                  case when a.relation='父亲'
                         then '父亲(年龄)'+' '+a.toplimit+'-'+a.downlimit
                        when a.relation='子女'
                          then '子女(身高)'+' '+a.toplimit+'-'+a.downlimit
                  end as relation
           from   Relation_limit a
         ) a
    order by relation-- 定义动态SQL
    declare @sql varchar(8000)
    select @sql = '
           select ' + left(@select_name,len(@select_name)-1) + '
           from   relation_pivot a
           pivot
           (max(person_num) for relation in (' + left(@pivot_name,len(@pivot_name)-1) + ')) b
           order by route' 
    exec (@sql)-- 结果
    -- 结果                                                                                                      
    route  [父亲(年龄) 50-60] [父亲(年龄) 61-70] [子女(身高) 100-110] [子女(身高) 111-120] [子女(身高) 121-130]  
    ------ ------------       ------------       --------------       --------------       --------------        
    A      1                  1                  1                    1                    0                     
    B      0                  1                  1                    0                    0                     
                                                                                                                
      

  6.   

    回#7--> 测试数据:#1
    if object_id('tempdb.dbo.#1') is not null drop table #1
    create table #1(id int, fid varchar(8), route varchar(8))
    insert into #1
    select 1, '1,2', 'A' union all
    select 2, '3,4', 'B' union all
    select 3, '5,6', 'A'
    --> 测试数据:#2if object_id('tempdb.dbo.#2') is not null drop table #2
    create table #2(id int, relation varchar(8), height int, age int)
    insert into #2
    select 1, '子女', 110, null union all
    select 2, '父亲', null, 60 union all
    select 3, '子女', 110, null union all
    select 4, '父亲', null, 65 union all
    select 5, '子女', 110, null union all
    select 6, '父亲', null, 65
    --> 测试数据:#3
    if object_id('tempdb.dbo.#3') is not null drop table #3
    create table #3(relation varchar(8), toplimit int, downlimit int)
    insert into #3
    select '子女', 100, 110 union all
    select '子女', 111, 120 union all
    select '子女', 121, 130 union all
    select '父亲', 50, 60 union all
    select '父亲', 100, 110declare @sql varchar(8000)
     set @sql='select a.route'
     select @sql=@sql +',sum(case when c.toplimit='+ltrim(toplimit)+' and c.downlimit='+ltrim(downlimit)+' then 1 else 0 end )as ['+ltrim(toplimit)+'-'+ltrim(downlimit)+']'
     from (select toplimit,downlimit from #3) m
    print @sql
     set @sql=@sql+'from #1 a, #2 b, #3 c
    where '+''',''+'+'a.fid'+'+'','''+' like '+'''%,''+'+'ltrim(b.id)'+'+'',%'''+'
    and b.relation=c.relation and isnull(b.height,b.age) between c.toplimit and c.downlimit
    group by a.route'
    print @sql
    exec(@sql)上面代码中如果子女身高和父亲年龄重叠,则会导致统计不正确!
      

  7.   

    如果相同的话的,则应该区分身高与年龄
    再加上判断! select @sql=@sql +',sum(case when b.height is not null and c.toplimit='+ltrim(toplimit)+' and c.downlimit='+ltrim(downlimit)+' then 1 else 0 end )as [Height'+ltrim(toplimit)+'-'+ltrim(downlimit)+']'+',sum(case when b.age is not null and c.toplimit='+ltrim(toplimit)+' and c.downlimit='+ltrim(downlimit)+' then 1 else 0 end )as [Age'+ltrim(toplimit)+'-'+ltrim(downlimit)+']'
      

  8.   

    学习7楼的方法,sum()稍作修改即可避免楼上所说问题。declare @sql1 varchar(8000)
     set @sql1='select a.route'
     select @sql1=@sql1 +',sum(case when c.toplimit='+ltrim(toplimit)+' and c.downlimit='+ltrim(downlimit)+' and c.relation = ''' + relation + ''' then 1 else 0 end )as '+quotename(relation+ ' ('+ltrim(toplimit)+'-'+ltrim(downlimit)+')')
     from (select toplimit,downlimit,relation from #3) m
    --print @sql
     set @sql1=@sql1+'from #1 a, #2 b, #3 c
    where '+''',''+'+'a.fid'+'+'','''+' like '+'''%,''+'+'ltrim(b.id)'+'+'',%'''+'
    and b.relation=c.relation and isnull(b.height,b.age) between c.toplimit and c.downlimit
    group by a.route'
    print @sql1
    exec(@sql1)