首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 求高手讲解一段SQL语句,关于distinct [已结贴,结贴人:fir521522]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-06-19 01:44:07 楼主
    前面我把这个题目贴出去解决了答案的问题,现在又疑惑了,一些回帖中的针对第四题的语句是怎么得到那个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 返回唯一值的和。


    100  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • knowjava
    • 等级:
    发表于:2008-06-19 06:26:311楼 得分:1
    坐等高手.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-06-19 08:18:172楼 得分:12
    SQL code
    --这样楼主可能容易看懂一点: 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.项目名称
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-06-19 08:22:003楼 得分:12
    SQL code
    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
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-06-19 08:23:404楼 得分:5
    distinct避免了重复统计
    up
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-06-19 08:27:215楼 得分:12
    因为[付款]表中合同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.合同编号
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-06-19 08:32:416楼 得分:12
    引用 5 楼 Novelty 的回复:
    因为[付款]表中合同1有两笔付款记录,使用left join联结查询会生成两条合同1记录,合同金额都是1500,使用sum合计的时候结果就多了1500,所以这里需要使用DISTINCT过滤合同号相同的记录进行sum,

    Distinct的目的是相同的合同的合同金额只计算一次,
    也可以使用Avg或者其它类似的聚合函数针对单个合同进行聚合,也是一回事.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-06-19 08:32:557楼 得分:20
    一高手给出的正确答案是:
    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楼的思路,下面的语句。
    SQL code
    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.项目名称
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-06-19 08:45:248楼 得分:26
    上一贴我在12楼写了:
    SQL code
    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楼说到"不对"
    然后写了:
    SQL code
    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


    看来楼主被我误导了,不好意思.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-06-19 12:42:199楼 得分:0
    哪里哪里~~
    是我自以为上贴12楼的比较简洁才只贴了12楼的,真不好意思。早知道13楼的也贴上来了。。

    十分感谢你再次回帖!!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-06-19 12:57:4610楼 得分:0


    OK ! 结贴 !
    再次感谢各位大侠们!!

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-06-19 13:04:2011楼 得分:0

    如果要用left join
    SQL code
    select 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.项目名称


    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved