有如下sql语句:select zonecode as zonecode,
       sum(t.counts) as counts,
       sum(case
             when t.flwcount = 1 then
              1
             else
              0
           end) as sumflw1, --完成一次w
       sum(case
             when t.flwcount = 2 then
              1
             else
              0
           end) as sumflw2, --完成两次w
       sum(case
             when t.flwcount = 2 then
              1
             else
              0
           end) as sumflw3, --完成三次w
       sum(case
             when t.flwcount = 2 then
              1
             else
              0
           end) as sumflw4, --完成四次w
       sum(case
             when t.cd4count = 1 then
              1
             else
              0
           end) as cd41, --完成一次a检测
       sum(case
             when t.cd4count = 2 then
              1
             else
              0
           end) as cd42, --完成两次a检测
       sum(case
             when t.virunlncount = 1 then
              1
             else
              0
           end) as viruln1, --完成一次c检测
       sum(t.virunlnno) as noviruln ,--c被抑制 
       sum(t.initvirunlncount) as avirulnsum
  from (select /*+ index(a PK_AIDSZH_SGRA_ADULT_INFO) */ a.card_id as card_id,
               a.zonecode as zonecode,
               sum(case
                     when a.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                          a.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') then
                      1
                     else
                      0
                   end) as counts,
               0 as flwcount, -- 当年完成w次数
               sum(case
                     when a.cd4 is not null and
                          a.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                          a.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') then
                      1
                     else
                      0
                   end) as cd4count, --当年完成a检测数
               sum(case
                     when a.viruln is not null and
                          a.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                          a.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') then
                      1
                     else
                      0
                   end) as virunlncount, --当年完成c次数
               0 as virunlnno,
                sum(case
                     when a.viruln is not null and
                          a.DT_ANTIVIRUS >= to_date('2009-01-01', 'yyyy-mm-dd') and
                          a.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') then
                      1
                     else
                      0
                   end) as initvirunlncount
          from aidszh_sgra_adult_info a
         where not exists (select ''
                  from aidszh_sgra_adult_flw m
                 where a.card_id = m.card_id) 
                 and a.zonecode like '11%'  
         group by a.card_id, a.zonecode
        union all
        select /*+ index(b PK_AIDISZH_SGRA_CHILD) index(c IDX_SGRA_adult_FLW) index(d IDX_SGRA_NEW_adult_IDCARD) */ b.card_id,
               b.zonecode as zonecode,
              /* sum(case
                     when b.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                          c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                          c.is_flw = '1' and c.clinic_treatment != '3' and ( d.end_cause <>'1' and d.end_cause <>'2' or d.end_cause is null ) then
                      1
                     else
                      0
                   end) as counts, --总人数,但是产生了笛卡尔积 */
                   count(distinct(b.card_id)) --总人数,但是缺少限制条件
               sum(case
                     when c.card_id is not null and
                          b.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                          c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                          c.is_flw = '1' and c.clinic_treatment != '3' and ( d.end_cause <>'1' and d.end_cause <>'2' or d.end_cause is null ) then
                      1
                     else
                      0
                   end) as flwcount, --当年完成w次数
               sum(case
                     when c.cd4 is not null and
                          b.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                          c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                          c.is_flw = '1' and c.clinic_treatment != '3' and ( d.end_cause <>'1' and d.end_cause <>'2' or d.end_cause is null ) then
                      1
                     else
                      0
                   end) as cd4count, --完成a检测数
               sum(case
                     when c.viruln is not null and
                          b.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                          c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                          c.is_flw = '1' and c.clinic_treatment != '3' and ( d.end_cause <>'1' and d.end_cause <>'2' or d.end_cause is null ) then
                      1
                     else
                      0
                   end) as virunlncount,
               sum(case
                     when b.viruln is not null and b.viruln <> '0' and
                          c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                          b.DT_ANTIVIRUS > to_date('2009-01-01', 'yyyy-mm-dd') and
                          c.viruln = '0' and
                          (c.dt_flworinterp - b.DT_ANTIVIRUS >= 180) and
                          (c.dt_flworinterp - b.DT_ANTIVIRUS <= 360) 
                           and
                          c.is_flw = '1' and c.clinic_treatment != '3' and ( d.end_cause <>'1' and d.end_cause <>'2' or d.end_cause is null ) then
                      1
                     else
                      0
                   end) as virunlnno, --c被抑制
                   sum(case
                     when b.viruln is not null and
                          b.DT_ANTIVIRUS >= to_date('2009-01-01', 'yyyy-mm-dd') and
                          c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                          c.is_flw = '1' and c.clinic_treatment != '3' and ( d.end_cause <>'1' and d.end_cause <>'2' or d.end_cause is null ) then
                      1
                     else
                      0
                   end) as initvirunlncount
          from aidszh_sgra_adult_info b, aidszh_sgra_adult_flw c,aidszh_sgra_adult_newstatus d
         where b.card_id = c.card_id and d.card_id=b.card_id 
         and b.zonecode like '11%'
         group by b.card_id, b.zonecode) t
 group by zonecode
上述sql中,我本想通过sum(case
                     when b.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                          c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                          c.is_flw = '1' and c.clinic_treatment != '3' and ( d.end_cause <>'1' and d.end_cause <>'2' or d.end_cause is null ) then
                      1
                     else
                      0
                   end) as counts
 求出符合某个条件的b表的人数,不料b表和c表是一对多的关系,产生了笛卡尔积,统计的人数远远大于实际的人数。
  后来我用count(distinct(b.card_id))求出b表中的人数,但是无法添加b表和c表的限制条件,只能求出全部的。事实上我想求出b表和c表tm_carete字段符合某个条件的b表的人数。
请大家指教!
对了,b表和c表是一对多的关系。b表和d表是一对一的关系。
如果上述sql不好改,那么请帮忙重写一个,要求如下:我要求出符合某些条件的所有人数、完成1次w的人数、完成2次w的人数、完成1次c的人数、完成2次c的人数。多谢。

解决方案 »

  1.   

    太长了,建议改变一下你的提问方式。建议你列出你的表结构,并提供测试数据以及基于这些测试数据的所对应正确结果。
       参考一下这个贴子的提问方式http://topic.csdn.net/u/20091130/20/8343ee6a-417c-4c2d-9415-fa46604a00cf.html
       
       1. 你的 create table xxx .. 语句
       2. 你的 insert into xxx ... 语句
       3. 结果是什么样,(并给以简单的算法描述)
       4. 你用的数据库名称和版本(经常有人在MS SQL server版问 MySQL)
       
       这样想帮你的人可以直接搭建和你相同的环境,并在给出方案前进行测试,避免文字描述理解上的误差。   
      

  2.   

    select zonecode as zonecode,
           sum(t.counts) as counts,
           sum(case
                 when t.flwcount = 1 then
                  1
                 else
                  0
               end) as sumflw1, --完成一次w
           sum(case
                 when t.flwcount = 2 then
                  1
                 else
                  0
               end) as sumflw2, --完成两次w
           sum(case
                 when t.flwcount = 2 then
                  1
                 else
                  0
               end) as sumflw3, --完成三次w
           sum(case
                 when t.flwcount = 2 then
                  1
                 else
                  0
               end) as sumflw4, --完成四次w
           sum(case
                 when t.cd4count = 1 then
                  1
                 else
                  0
               end) as cd41, --完成一次a检测
           sum(case
                 when t.cd4count = 2 then
                  1
                 else
                  0
               end) as cd42, --完成两次a检测
           sum(case
                 when t.virunlncount = 1 then
                  1
                 else
                  0
               end) as viruln1, --完成一次c检测
           sum(t.virunlnno) as noviruln, --c被抑制 
           sum(t.initvirunlncount) as avirulnsum
      from (select /*+ index(a PK_AIDSZH_SGRA_ADULT_INFO) */
             a.card_id as card_id,
             a.zonecode as zonecode,
             sum(case
                   when a.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                        a.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') then
                    1
                   else
                    0
                 end) as counts,
             0 as flwcount, -- 当年完成w次数
             sum(case
                   when a.cd4 is not null and
                        a.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                        a.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') then
                    1
                   else
                    0
                 end) as cd4count, --当年完成a检测数
             sum(case
                   when a.viruln is not null and
                        a.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                        a.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') then
                    1
                   else
                    0
                 end) as virunlncount, --当年完成c次数
             0 as virunlnno,
             sum(case
                   when a.viruln is not null and
                        a.DT_ANTIVIRUS >= to_date('2009-01-01', 'yyyy-mm-dd') and
                        a.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') then
                    1
                   else
                    0
                 end) as initvirunlncount
              from aidszh_sgra_adult_info a
             where not exists (select ''
                      from aidszh_sgra_adult_flw m
                     where a.card_id = m.card_id)
               and a.zonecode like '11%'
             group by a.card_id, a.zonecode
            union all
            select /*+ index(b PK_AIDISZH_SGRA_CHILD) index(c IDX_SGRA_adult_FLW) index(d IDX_SGRA_NEW_adult_IDCARD) */
             b.card_id,
             b.zonecode as zonecode,
             /* sum(case
                                   when b.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                                        c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                                        c.is_flw = '1' and c.clinic_treatment != '3' and ( d.end_cause <>'1' and d.end_cause <>'2' or d.end_cause is null ) then
                                    1
                                   else
                                    0
                                 end) as counts, --总人数,但是产生了笛卡尔积 */
             count(distinct(b.card_id)) --总人数,但是缺少限制条件
              sum(case
               when c.card_id is not null and
                    b.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                    c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                    c.is_flw = '1' and c.clinic_treatment != '3' and
                    (d.end_cause <> '1' and d.end_cause <> '2' or
                    d.end_cause is null) then
                1
               else
                0
             end) as flwcount, --当年完成w次数
             sum(case
                   when c.cd4 is not null and
                        b.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                        c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                        c.is_flw = '1' and c.clinic_treatment != '3' and
                        (d.end_cause <> '1' and d.end_cause <> '2' or
                        d.end_cause is null) then
                    1
                   else
                    0
                 end) as cd4count, --完成a检测数
             sum(case
                   when c.viruln is not null and
                        b.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                        c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                        c.is_flw = '1' and c.clinic_treatment != '3' and
                        (d.end_cause <> '1' and d.end_cause <> '2' or
                        d.end_cause is null) then
                    1
                   else
                    0
                 end) as virunlncount,
             sum(case
                   when b.viruln is not null and b.viruln <> '0' and
                        c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                        b.DT_ANTIVIRUS > to_date('2009-01-01', 'yyyy-mm-dd') and
                        c.viruln = '0' and (c.dt_flworinterp - b.DT_ANTIVIRUS >= 180) and
                        (c.dt_flworinterp - b.DT_ANTIVIRUS <= 360) and c.is_flw = '1' and
                        c.clinic_treatment != '3' and
                        (d.end_cause <> '1' and d.end_cause <> '2' or
                        d.end_cause is null) then
                    1
                   else
                    0
                 end) as virunlnno, --c被抑制
             sum(case
                   when b.viruln is not null and
                        b.DT_ANTIVIRUS >= to_date('2009-01-01', 'yyyy-mm-dd') and
                        c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                        c.is_flw = '1' and c.clinic_treatment != '3' and
                        (d.end_cause <> '1' and d.end_cause <> '2' or
                        d.end_cause is null) then
                    1
                   else
                    0
                 end) as initvirunlncount
              from aidszh_sgra_adult_info b,
                   (select card_id,
                           tm_create,
                           viruln,
                           dt_flworinterp,
                           is_flw,
                           clinic_treatment
                      from aidszh_sgra_adult_flw
                     group by card_id,
                              tm_create,
                              viruln,
                              dt_flworinterp,
                              is_flw,
                              clinic_treatment) c,
                   (select card_id, end_cause
                      from aidszh_sgra_adult_newstatus
                     group by card_id, end_cause) d
             where b.card_id = c.card_id
               and d.card_id = b.card_id
               and b.zonecode like '11%'
             group by b.card_id, b.zonecode) t
     group by zonecode
    这里你得注意一点,由于我没有你的数据表不能确定
    (select card_id,
                           tm_create,
                           viruln,
                           dt_flworinterp,
                           is_flw,
                           clinic_treatment
                      from aidszh_sgra_adult_flw
                     group by card_id,
                              tm_create,
                              viruln,
                              dt_flworinterp,
                              is_flw,
                              clinic_treatment) c
                   (select card_id, end_cause
                      from aidszh_sgra_adult_newstatus
                     group by card_id, end_cause) d
    这两个表按这些条件group by 后是不是每个card_id只有一条记录
      

  3.   

    看你的这SQL语法有问题
    sum(case
                         when b.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                              c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                              c.is_flw = '1' and c.clinic_treatment != '3' and ( d.end_cause <>'1' and d.end_cause <>'2' or d.end_cause is null ) then
                          1
                         else
                          0
                       end) as counts
    不知道你要的是什么结果
    (d.end_cause <>'1' and (d.end_cause <>'2' or d.end_cause is null))((d.end_cause <>'1' and d.end_cause <>'2') or d.end_cause is null)
      

  4.   

    在一位热心朋友的帮助下,sql做了一点小的更改,就查出了正确的结果:加了一个decode函数,多加了一列couont1.
    sql如下:select zonecode as zonecode,
           sum(t.count1)+sum(decode(t.counts,0,0,1)) as counts,
           sum(case
                 when t.flwcount = 1 then
                  1
                 else
                  0
               end) as sumflw1, --完成一次w
           sum(case
                 when t.flwcount = 2 then
                  1
                 else
                  0
               end) as sumflw2, --完成两次w
           sum(case
                 when t.flwcount = 2 then
                  1
                 else
                  0
               end) as sumflw3, --完成三次w
           sum(case
                 when t.flwcount = 2 then
                  1
                 else
                  0
               end) as sumflw4, --完成四次w
           sum(case
                 when t.cd4count = 1 then
                  1
                 else
                  0
               end) as cd41, --完成一次a检测
           sum(case
                 when t.cd4count = 2 then
                  1
                 else
                  0
               end) as cd42, --完成两次a检测
           sum(case
                 when t.virunlncount = 1 then
                  1
                 else
                  0
               end) as viruln1, --完成一次c检测
           sum(t.virunlnno) as noviruln ,--c被抑制 
           sum(t.initvirunlncount) as avirulnsum
      from (select /*+ index(a PK_AIDSZH_SGRA_ADULT_INFO) */ a.card_id as card_id,
                   a.zonecode as zonecode,
                   0 as counts,
                   sum(case
                         when a.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                              a.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') then
                          1
                         else
                          0
                       end) as count1,
                   0 as flwcount, -- 当年完成w次数
                   sum(case
                         when a.cd4 is not null and
                              a.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                              a.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') then
                          1
                         else
                          0
                       end) as cd4count, --当年完成a检测数
                   sum(case
                         when a.viruln is not null and
                              a.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                              a.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') then
                          1
                         else
                          0
                       end) as virunlncount, --当年完成c次数
                   0 as virunlnno,
                    sum(case
                         when a.viruln is not null and
                              a.DT_ANTIVIRUS >= to_date('2009-01-01', 'yyyy-mm-dd') and
                              a.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') then
                          1
                         else
                          0
                       end) as initvirunlncount
              from aidszh_sgra_adult_info a
             where not exists (select ''
                      from aidszh_sgra_adult_flw m
                     where a.card_id = m.card_id) 
                     and a.zonecode like '11%'  
             group by a.card_id, a.zonecode
            union all
            select /*+ index(b PK_AIDISZH_SGRA_CHILD) index(c IDX_SGRA_adult_FLW) index(d IDX_SGRA_NEW_adult_IDCARD) */ b.card_id,
                   b.zonecode as zonecode,
                  sum(case
                         when b.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                              c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                              c.is_flw = '1' and c.clinic_treatment != '3' and ( d.end_cause <>'1' and d.end_cause <>'2' or d.end_cause is null ) then
                          1
                         else
                          0
                       end) as counts, 
                       0 as count1,
                   sum(case
                         when c.card_id is not null and
                              b.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                              c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                              c.is_flw = '1' and c.clinic_treatment != '3' and ( d.end_cause <>'1' and d.end_cause <>'2' or d.end_cause is null ) then
                          1
                         else
                          0
                       end) as flwcount, --当年完成w次数
                   sum(case
                         when c.cd4 is not null and
                              b.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                              c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                              c.is_flw = '1' and c.clinic_treatment != '3' and ( d.end_cause <>'1' and d.end_cause <>'2' or d.end_cause is null ) then
                          1
                         else
                          0
                       end) as cd4count, --完成a检测数
                   sum(case
                         when c.viruln is not null and
                              b.DT_ANTIVIRUS <= to_date('2008-12-31', 'yyyy-mm-dd') and
                              c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                              c.is_flw = '1' and c.clinic_treatment != '3' and ( d.end_cause <>'1' and d.end_cause <>'2' or d.end_cause is null ) then
                          1
                         else
                          0
                       end) as virunlncount,
                   sum(case
                         when b.viruln is not null and b.viruln <> '0' and
                              c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                              b.DT_ANTIVIRUS > to_date('2009-01-01', 'yyyy-mm-dd') and
                              c.viruln = '0' and
                              (c.dt_flworinterp - b.DT_ANTIVIRUS >= 180) and
                              (c.dt_flworinterp - b.DT_ANTIVIRUS <= 360) 
                               and
                              c.is_flw = '1' and c.clinic_treatment != '3' and ( d.end_cause <>'1' and d.end_cause <>'2' or d.end_cause is null ) then
                          1
                         else
                          0
                       end) as virunlnno, --c被抑制
                       sum(case
                         when b.viruln is not null and
                              b.DT_ANTIVIRUS >= to_date('2009-01-01', 'yyyy-mm-dd') and
                              c.tm_create <= to_date('2006-06-30', 'yyyy-mm-dd') and
                              c.is_flw = '1' and c.clinic_treatment != '3' and ( d.end_cause <>'1' and d.end_cause <>'2' or d.end_cause is null ) then
                          1
                         else
                          0
                       end) as initvirunlncount
              from aidszh_sgra_adult_info b, aidszh_sgra_adult_flw c,aidszh_sgra_adult_newstatus d
             where b.card_id = c.card_id and d.card_id=b.card_id 
             and b.zonecode like '11%'
             group by b.card_id, b.zonecode) t
     group by zonecode