回 帖 发 新 帖 刷新版面

主题:[请教] 以表1中编号为关键字,统计表2中相同编号的数量的SQL语句如何写?

表1中有字段BH(编号),以该BH为关键字,统计表2中相同编号的数量,也就是对表2中的SL求和,再把求和结果写入表1的N_SL。
SQL语句如应何写?十分感谢!

回复列表 (共33个回复)

21 楼

各位坛友好:
    一开始我就在思考这样一个问题,这种用SQL语句以表1中的BH去查找表2中的的对应BH统计或求和,是不是表1中的每一条都要查遍表2的所有记录,如果是那样,表2的记录很多时会很慢的。如果不用SQL语句我倒是会写按顺序分段统计的程序段,但不知哪种能更好?

22 楼

UPDATE 表1 SET 表1.N_SL =b.sl from 表1 a,(select bh,SUM(sl) as sl from 表2 group by bh) b WHERE a.bh=b.bh

UPDATE 表1 SET 表1.N_SL =b.sl from 表1 a inner join (select bh,SUM(sl) as sl from 表2 group by bh) b on a.bh=b.bh

UPDATE 表1 SET N_SL = a.sl from (SELECT bh, sum(sl) sl FROM 表2 a GROUP BY a.bh) a WHERE 表1.bh=a.bh

这三中方式在sql查询分析器里执行都对.vfp9.0里前两种情况不对?为什么?

23 楼

回21楼:
SQL是结构化查询语句,它的优点是高效,缺点是不能控制流程,如果用它可以代替一段流程语句,它的效率无疑是最高的.这是晚辈的理解,仅供参考.

回楼上:
查询分析器是不是SQL SERVER里的寻个查询分析器,SQLSERVER和VFP是两个不同DBMS,其对SQL语句的支持程序是不一样的,它们都对SQL标准语句进行了各自的扩充.所以在前者可以支持的语句在后者就不一定支持.
如果你把前两个语句中的数据表或查询的别名都用两个以上的字符标识,或者就可以在VFP中运行,不信你试试看.

24 楼

[b]其实并不是两个字符作为别名, 看了下F9 是一旦使用别名,所以地方都必须使用[/b][quote]UPDATE 表1 SET 表1.N_SL =b.sl from 表1 a,(select bh,SUM(sl) as sl from 表2 group by bh) b WHERE a.bh=b.bh

UPDATE 表1 SET 表1.N_SL =b.sl from 表1 a inner join (select bh,SUM(sl) as sl from 表2 group by bh) b on a.bh=b.bh

UPDATE 表1 SET N_SL = a.sl from (SELECT bh, sum(sl) sl FROM 表2 a GROUP BY a.bh) a WHERE 表1.bh=a.bh

这三中方式在sql查询分析器里执行都对.vfp9.0里前两种情况不对?为什么?[/quote]


FROM 子句的详细语法如下:

 
FROM [FORCE] Table_List_Item [, ...]
      [[JoinType] JOIN DatabaseName!]Table [[AS][b] Local_Alias[/b]]
      [ON JoinCondition [AND | OR [JoinCondition | FilterCondition] ...]
 

参数
Table_List_Item [, ...] 
指定一个或多个包含查询从中检索数据的表。Table_List_Item 可以用以下语法:
[DatabaseName!]Table [[AS] Local_Alias] DatabaseName! 如果表在非当前数据库中,指定包含表的数据库名。如果表在非当前数据库中,则必须包含数据库名。在数据库名之后、表名之前,用一个惊叹号(!)作为分隔符。 Table 指定想要从中检索数据的表名。如果表没有打开,Visual FoxPro 将显示打开对话框,您可以指定文件位置。表打开后,直到查询完成都保持打开。 Local_Alias 为 Table 中指定的表指定一个临时名。[b]如果指定了一个本地别名,则在 SELECT 语句的所有位置,都必须使用本地别名代替表名。[/b] 不限制每条 SELECT 语句中表和别名的数量。也可以通过使用一条或多条 JOIN 子句指定多张表。 

*--------------------------------------------------------------------------
正如在VF中,下面例子就说明了问题

CREATE CURSOR Tmp1 (a c(10),b i)

CREATE CURSOR Tmp2 (a c(10),b i)

INSERT INTO Tmp1 (a,b) VALUES ('a',1)
INSERT INTO Tmp1 (a,b) VALUES ('b',2)
INSERT INTO Tmp1 (a,b) VALUES ('c',3)
INSERT INTO Tmp1 (a,b) VALUES ('d',4)


INSERT INTO Tmp2 (a,b) VALUES ('a',0)
INSERT INTO Tmp2 (a,b) VALUES ('d',0)


[b]UPDATE Tmp2 SET b=t2.b ;
from Tmp2  t1 inner join  Tmp1 t2 on t1.a=t2.a  &&错误[/b]

[b]*-因为上面已经把Tmp2 别名为t1 所以必须改为SET t1.b=t2.b 
*-这就是MS-SQL与VFP中一点区别,部分人把他当BUG,不过F9已经说明很清楚了[/b]

SELECT tmp2
BROWSE

[b]UPDATE Tmp2 SET b=tmp1.b ;
from Tmp2  inner join Tmp1  on Tmp2.a=Tmp1.a  &&正确[/b]

SELECT tmp2
brow

25 楼

十分感谢各位坛友回帖!
由于本人对SQL似懂非懂,所以还是没弄清哪帖是最佳答案,有请哪位朋友再给注明一下。
我还是在想这种用SQL语句以表1中的BH去查找表2中的的对应BH统计或求和,是不是表1中的每一条都要查遍表2的所有记录,如果是那样,表2的记录很多时会很慢的。
如果不用SQL语句我倒是会写按顺序分段统计的程序段,但不知哪种能更好?

26 楼

种子大叔:晚辈刚系统地学完了SQL语言,正在应用中,可能有很多地方还没吃透,但对您这个问题比较有把握,其他各位前辈的回贴我都看了,自认为我的回答最简明扼要:
update 表1 set n_sl = (select sum(n_sl) from 表2 where bh = 表1.bh);
where bh in (select bh from 表2)

下面给你解释一下:
SQL语句是结构化查询语句(Structured Query Language),SQL是三个英文单词第一个字母的缩写,它包括数据定义,数据操作和数据控制三个部分,其中数据操作又分为数据更新与数据查询两类,数据更新又分为插入记录,删除记录和修改记录三种,您的问题是修改表1中的记录,而被修改记录中n_sl的值是表2中具有相同编号(bh)的记录的sl字段的值的总和.表1中只有那些在表2中有相应记录(编号相同的)的记录的n_sl值才被修改.所以,我为您提供了上列语句,它是一个嵌套的或者说带有子查询的SQL语句.
update语句的基本格式是:
update <表名> set <字段名> = <值>[,<字段名>=<值>,...] where <条件表达式>
<条件表达式> 是被修改的记录必须满足的条件,即只有满足某一条件的记录才被修改.
<值>可以用具体的值,也可以用查询语句,只要查询语句查的结果是一个值

update 表1 set n_sl = (select sum(sl) from 表2 where bh = 表1.bh);
where bh in (select distinct bh from 表2)
上列第二行是<条件表达式>中带子查询,"select distinct bh from 表2"查出在表2中所有bh的值,"distinct"是一个关键字,表示bh值不重复,在表2中可能有很多记录具有相同的编号值,表2中如果有1万条记录,各不相同的编号值可能只有几千或者几百个.所以,这个语句查询的结果是一组值的集合,"in"是在其中的意思, "bh in (select...)"表示表1中被修改记录的bh必须是"select distinct bh from 表2"查到的值集中的某一个.
"update 表1 set n_sl = (select sum(sl) from 表2 where bh = 表1.bh)"会对表1中满足"bh in (select distinct bh from 表2)"条件的记录一条接一条的修改,
例如修改编号为"0002"的记录的n_sl时,用"select sum(sl) from 表2 where bh = 表1.bh"(此时其中的"表1.bh"就是"0002")语句统计出表2中编号为"0002"的全部记录的sl值的总和,赋值给表1的n_sl.

种子大叔,我可能写得罗索了.希望能帮到您.你担心的当表2中记录很多时会慢的问题没有必要,SQL语句的特点就是高效,任何过程化的代码都没有它高效.但就SQL本身而言,使用嵌套查询时尽量避免用相关子查询会更加高效.

27 楼

种子老哥,看看我是不是这样理解您老的问题的?

举例 :

1、表一 为销售汇总库 有 BH(编号),N_SL(数量)  编号 是关键字 且各编号是唯一的。
2、表二 为销售流水库 有 BH(编号),SL(数量) 编号 是关键字 且有许多条编号相同且数量不同的记录。您老是想把销售流水库按编号汇总数量?

如果是这样的话,对我的DB来说就是用 “多对一更新”功能 关键字是“编号” 更新表达式是“N_SL+ab->SL” (ab是流水表别名)几个简单的语句就搞掂。

28 楼

[quote]种子大叔:晚辈刚系统地学完了SQL语言,正在应用中,可能有很多地方还没吃透,但对您这个问题比较有把握,其他各位前辈的回贴我都看了,自认为我的回答最简明扼要:
update 表1 set n_sl = (select sum(n_sl) from 表2 where bh = 表1.bh);
where bh in (select bh from 表2)

下面给你解释一下:
SQL语句是结构化查询语句(Structured Query Language),SQL是三个英文单词第一个字母的缩写,它包括数据定义,数据操作和数据控制三个部分,其中数据操作又分为数据更新与数据查询两类,数据更新又分为插入记录,删除记录和修改记录三种,您的问题是修改表1中的记录,而被修改记录中n_sl的值是表2中具有相同编号(bh)的记录的sl字段的值的总和.表1中只有那些在表2中有相应记录(编号相同的)的记录的n_sl值才被修改.所以,我为您提供了上列语句,它是一个嵌套的或者说带有子查询的SQL语句.
update语句的基本格式是:
update <表名> set <字段名> = <值>[,<字段名>=<值>,...] where <条件表达式>
<条件表达式> 是被修改的记录必须满足的条件,即只有满足某一条件的记录才被修改.
<值>可以用具体的值,也可以用查询语句,只要查询语句查的结果是一个值

update 表1 set n_sl = (select sum(sl) from 表2 where bh = 表1.bh);
where bh in (select distinct bh from 表2)
上列第二行是<条件表达式>中带子查询,"select distinct bh from 表2"查出在表2中所有bh的值,"distinct"是一个关键字,表示bh值不重复,在表2中可能有很多记录具有相同的编号值,表2中如果有1万条记录,各不相同的编号值可能只有几千或者几百个.所以,这个语句查询的结果是一组值的集合,"in"是在其中的意思, "bh in (select...)"表示表1中被修改记录的bh必须是"select distinct bh from 表2"查到的值集中的某一个.
"update 表1 set n_sl = (select sum(sl) from 表2 where bh = 表1.bh)"会对表1中满足"bh in (select distinct bh from 表2)"条件的记录一条接一条的修改,
例如修改编号为"0002"的记录的n_sl时,用"select sum(sl) from 表2 where bh = 表1.bh"(此时其中的"表1.bh"就是"0002")语句统计出表2中编号为"0002"的全部记录的sl值的总和,赋值给表1的n_sl.

种子大叔,我可能写得罗索了.希望能帮到您.你担心的当表2中记录很多时会慢的问题没有必要,SQL语句的特点就是高效,任何过程化的代码都没有它高效.但就SQL本身而言,使用嵌套查询时尽量避免用相关子查询会更加高效.[/quote]

您的观点我不完全赞同,我不是说SQL语句不高效,而是在一些特定的情况下,比如用自由表在记录数很大如上百万条记录的情况下和全部只用SQL数据库时查询效率是没法比的如兴趣你可搞一下测试就知道了。

29 楼

感谢诸位
献计献策
仍没搞定
继续征集

30 楼

那些高手的语句是两句并作一局,难度较大。

select bh,sum(shuliang) from biao2 group by bh into cursor tempbiao
 
这句明白?

我来回复

您尚未登录,请登录后再回复。点此登录或注册