前面我把这个题目贴出去解决了答案的问题,现在又疑惑了,一些回帖中的针对第四题的语句是怎么得到那个4000的数的,恳请高手详情讲解。
请没有看到前一贴的朋友先看完题目。题如下: 
问题说明:有三个表,项目表、合同表、付款表 
一个项目可能会有签署多个合同,每个合同会分几次付款。 --下面是建立表的语句 
create table 项目(项目编号 int,项目名称 varchar(50)) 
insert 项目 
select 1, '项目1' 
union 
select 2, '项目2' 
union 
select 3, '项目3' 
create table 合同(合同编号 int,项目编号 int,合同金额 numeric(7,3)) insert 合同 
select 1,1,1000 
union 
select 2,1,1500 
union 
select 3,2,2000 create table 付款(付款编号 int,合同编号 int,付款金额 numeric(7,3)) insert 付款 
select 1,1,100 
union 
select 2,2,200 
union 
select 3,2,800 问题(四): 
请您设计一个查询语句,检索的格式如下: 
------------------------------------------------------------------------ 
项目编号    项目名称    项目所有合同的金额    项目所有合同已付款金额  
------------------------------------------------------------------------ 
1          项目1        2500.000              1100.000 
2          项目2        2000.000              NULL 
------------------------------------------------------------------------ 问题四考核连接、分组统计、子查询的综合运用 
此题得到了一些回帖基本如下:----------------------------------------------
select a.项目编号,a.项目名称,sum(合同金额) as 合同金额,sum(付款金额) as 付款金额
from 项目 a join 合同 b on a.项目编号=b.项目编号
left join 付款 c on b.合同编号=c.合同编号
group by a.项目编号,a.项目名称一高手给出的正确答案是:
select a.项目编号,a.项目名称,sum(distinct b.合同金额),sum(c.付款金额) 
from 项目 as a 
left join 合同 as b on a.项目编号=b.项目编号
left join 付款 as c on b.合同编号=c.合同编号
group by a.项目编号,a.项目名称---------------------------------------------
大家看到了,这里多了个distinct 我在帮助里找到了这个下面的解释,但是我还是不知道那个4000是怎么得来的。。SUM
返回表达式中所有值的和,或只返回 DISTINCT 值。SUM 只能用于数字列。空值将被忽略。语法
SUM ( [ ALL | DISTINCT ] expression ) 参数
ALL对所有的值进行聚合函数运算。ALL 是默认设置。DISTINCT指定 SUM 返回唯一值的和。

解决方案 »

  1.   


    --这样楼主可能容易看懂一点:
    select a.项目编号,a.项目名称,合同金额=sum(b.合同金额),付款金额=sum(b.付款金额) 
    from 项目 a,
    (select 项目编号,合同金额,付款金额=(select sum(付款金额) from 付款 where 合同编号=a.合同编号) from 合同 a)b
    where a.项目编号=b.项目编号
    group by a.项目编号,a.项目名称
      

  2.   

    select a.项目编号,a.项目名称,合同金额 as 合同金额,付款金额 as 付款金额
    from 项目 a join 合同 b on a.项目编号=b.项目编号
    left join 付款 c on b.合同编号=c.合同编号
    项目编号 项目名称 合同金额 付款金额
    1 项目1 1000.000 100.000
    1 项目1 1500.000 200.000
    1 项目1 1500.000 800.000
    2 项目2 2000.000 NULL
    连接后是这样的,3个项目1=4000,加distinct 就是1500+1000=2500
      

  3.   

    因为[付款]表中合同1有两笔付款记录,使用left join联结查询会生成两条合同1记录,合同金额都是1500,使用sum合计的时候结果就多了1500,所以这里需要使用DISTINCT过滤合同号相同的记录进行sum。你执行一下下面的查询就很直观了。select a.项目编号,a.项目名称,b.合同金额,c.付款金额
    from 项目 as a
    left join 合同 as b on a.项目编号=b.项目编号
    left join 付款 as c on b.合同编号=c.合同编号
      

  4.   

    Distinct的目的是相同的合同的合同金额只计算一次,
    也可以使用Avg或者其它类似的聚合函数针对单个合同进行聚合,也是一回事.
      

  5.   

    一高手给出的正确答案是: 
    select a.项目编号,a.项目名称,sum(distinct b.合同金额),sum(c.付款金额) 
    from 项目 as a 
    left join 合同 as b on a.项目编号=b.项目编号 
    left join 付款 as c on b.合同编号=c.合同编号 
    group by a.项目编号,a.项目名称 
    --------------------------------------------------------------------
    可以很负责的告诉你,高手给出的答案较前面给出的答案要正确些,但依然在某种巧合下产生错误。
    这种巧合就是存在某个项目中有两个或多个合同的金额相同的情况下。
    因此,正确的答案应该是:2楼的思路,下面的语句。
    select a.项目编号,a.项目名称,合同金额=sum(b.合同金额),付款金额=sum(b.付款金额) 
    from 项目 a  left join (select 项目编号,合同金额,付款金额=(select sum(付款金额) from 付款 where 合同编号=a.合同编号) from 合同 a)b
    on a.项目编号=b.项目编号
    group by a.项目编号,a.项目名称
      

  6.   

    上一贴我在12楼写了:
    select a.项目编号,a.项目名称,sum(distinct b.合同金额),sum(c.付款金额) 
    from 项目 as a 
    left join 合同 as b on a.项目编号=b.项目编号 
    left join 付款 as c on b.合同编号=c.合同编号 
    group by a.项目编号,a.项目名称 
    然后我发现错了,出来的结果是对的,但只是巧合.
    所以,我随即在13楼说到"不对"
    然后写了:
    select a.项目编号,a.项目名称,
    (select sum(合同金额) from 合同 where 项目编号=a.项目编号) as 项目所有合同的金额,
    (select sum(付款金额) from 付款 as b inner join  合同  as c on b.合同编号=c.合同编号 where c.项目编号=a.项目编号) as 项目所有合同已付款金额
    from 项目 as a 看来楼主被我误导了,不好意思.
      

  7.   


    如果要用left joinselect a.项目编号,a.项目名称,sum(t.项目所有合同的金额) as 项目所有合同的金额,sum(t.项目所有合同已付款金额) as 项目所有合同已付款金额
    from 项目 as a 
    left join (
        select b.项目编号,b.合同编号,max(b.合同金额) as 项目所有合同的金额,sum(c.付款金额) as 项目所有合同已付款金额
        from 合同 as b
        left join 付款 as c on b.合同编号=c.合同编号 
        group by b.项目编号,b.合同编号
    ) as t on a.项目编号=t.项目编号 
    group by a.项目编号,a.项目名称