




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Visual FoxPro 中的 SQL Select 查询基本的 SQL Select 3.From 子句 3.Select 子句 3.SQL 和用户自定义函数 4.Select 子句中的关键字和其它子句 4.Select 子句中的通配符 4.字段别名 (AS) 6.用 DISTINCT 消去重复的记录 6.用 WHERE 子句说明选择记录的条件 7.选择条件 7.连接条件 7.SQL 和宏 7SQL 和字母大小写 8.SQL 和索引 8.用 Order By 子句对结果排序 9.列函数 10SQL 的列函数 10列函数中的 DISTINCT 11列函数的嵌套 11用 GROUP BY 求分
2、组小计 15GROUP BY 和 DISTINCT 之间的选择 16HAVING 子句的使用 17用 TOP 子句选择一定数量或一定百分比的记录 24查询结果的输出定向 25复杂查询 26子查询 27带子查询的 IN 谓词和量词 27ANY|SOME 29ALL 30EXISTS 30自身连接 31合并 32示例一 .快速排名次 36示例二 .选择重复的记录 37外连接 38什么是外连接 ?38用右外连接 (Right Outer Join) 选择记录 39用左外连接 (Left Outer Join) 选择记录 41用完全外连接 (Full Outer Join) 选择记录 42用内连接加外
3、连接选择记录 43用内连接 (Inner Join) 选择记录 44用嵌套的连接 (Nested Join) 选择记录 45Visual FoxPro 5.0 中的新的 FROM/JOIN 语法 46为了更加清晰 48用 SQL Select 生成视图 52注意事项 53基本的 SQL SelectFrom 子句在 FROM 子句中指定要查询的表,若指定的表未打开, FoxPro 将自动打开指定的表,但在查询完成后FoxPro并不自动关闭它所打开的表,若要在查询完成后关闭表,则必须以手动方式关闭它们。若在执行SQL SELECT时,FROM 子句中指定的表已经打开,则FoxPro 以USEAG
4、AIN 的方式重新打开此表。Select 子句SELECT 子句中指定要查询的结果字段,这些结果可以是以下基本元素:通配符 *表中的字段名FoxPro 函数SELECT 中可用的列函数用户自定义函数常数 (常用于作为占位符 )以上各元素在 SELECT子句中以逗号分开,例如: SELECT 销售地区 ,销售部门 ,业务员 ;FROM 销售表若 SELECT 子句中的字段名是唯一的,则不必在字段名前加别名修饰, SQL 能自动找到这些字段。若字段名是非唯一的 (即同一字段名出现在 FROM 子句中的两个或两个以上表中 ), FoxPro 返回以下错误信息:字段| 变量 不唯一 ,必须加以限定要纠
5、正这一错误,用字段所在表的别名修饰该字段。若在 SELECT 子句中加入了 FoxPro 函数,则意味着该语句不具备可移植性。SQL 和用户自定义函数FoxPro 支持在 Select 子句中使用用户定义函数。但是由于在其它系统中不支持用户定义函数。因此在开 发可能移植的系统时不要使用用户自定义函数。Select 子句中的关键字和其它子句Select 子句中的通配符1、 (星号)只能使用在字段串列参数中。代表来源数据库中所有的字段。如果 select 是在二个以上的数据库中进 行查询的,则要在号码前加上数据库别名。* 是 SQL 中的三个通配符之一 ( 其它两个是 ? 和 _ ,将在以后讨论
6、),* 只能出现在 Select 子句中 ,通配 符前可以用别名修饰 ,在此情况下表示要查询指定工作区中的全部字段.同时还可以给出其它字段名 .如 :Select 销售表 .*, 客户表 .客户代码 , 客户表 .客户名称 ;FROM 销售表 , 客户表WHERE 销售表 .客户代码 =客户表 .客户代码2、%(百分号 )只能使用在 Where 参数中,代表一连串任意字符类似于 DOS 下的 IT*.PRG 中的 “ * ”。通常与运算 符 LIKE 搭配使用 :SELECT 客户名 FROM 客户表 WHERE 客户名 LIKE “成都 % 公司”以上查询选择所有公司名以”成都”开始,以”公
7、司”结尾的客户 ,如 :成都东方公司、成都西部发展公司等。3、_(下划线 )也只能使用在 where 参数中,代表一个任意字符。与 DOS 下的 DIR IT?.PRG 中的” ?”一样。例如 _a% 表示第二个字符为 a 的字串。通常与 LIKE 搭配使用 :SELECT 客户名 FROM 客户表 WHERE 客户名 LIKE “成都 _公司”以上查询选择类似于”成都分公司” , ”成都总公司”这样的公司名字。另一种情况是文字数据中正好包含有星号、百分号、下划线(例如:软件部 _业务组 ),此时可使用关键字 ESCAPE 告诉 SQL 哪一个字符是常数字符而非通配符。例如:select co
8、mpany from customerwhere company like%_% escape 此时 escape 所指定字符 (即) 后的那一个字段 (此处为下划线 _)将被视为常数字符而非通配符。字段别名 (AS)FoxPro 提供了给 Select 子句中的字段起别名的方法 (这种方法不同于 ANSI/ISO 标准 ):即可用 AS 子句给出 Select 子句中字段的别名 ,在多当需要直接浏览查询结果或查询结果中含有计算列时,该方法很有用处 .例如:SELECT “物资部” AS 部门 ,SUM( 工资 ) AS 工资汇总 ;FROM 工资表 ;WHERE 部门编号 = “ 0013
9、”用 DISTINCT 消去重复的记录SELECT 中的 DISTINCT 关键字 ,可以消去查询结果中的重复行。例如要字段出所有购买了商的客户,可以用以下 Select 语句 :SELECT DISTINCT 客户名称 ;FROM 销售细节表注意 ,这里消去的重复记录是指 SELECT 子句中的所有字段值均相等的记录 .当 SQL 遇到 DISTINCT 关键字时 , 即建立一个中间表。然后以SELECT 子句中的所有字段建立一个唯一索引,然后将索引用于中间表 ,并把索引中的记录放入查询结果中。 这样就消去了重复记录, 但是当 SELECT 子 句中的字段很多时 ,这一过程会很慢。用 WHE
10、RE 子句说明选择记录的条件通常查询并不希望取出所有记录 ,而只是希望查出满足一定条件的记录,要做到这一点可以使用WHERE 子句。 WHERE 子句把满足条件的记录作为查询结果。选择条件在 WHERE 子句中可以包含多个选择条件,各条件间用 AND 或 OR 连接而构成较长的逻辑表达式。连接条件当一个查询涉及到多个表时, 需要一个特殊类型的 WHERE 条件,称为连接条件, 连接条件建立了 FROM 子 句中的两表间的一对一或一对多的联系。SQL 和宏SELECT 子句中可以方便快捷地处理宏 ,在 SELECT 语句中 ,宏替换只能替换一次 ,在以下查询之前 ,需要由用 户给出表名和相应的表
11、达式Select * ;FROM (UserT able) ;Where 公司代码 = &Company_code宏还可以用在 LIKE 的模式匹配串 :Select Company,CompanyId,SaleName,SaleId ;From Company,SalesMan ;Where Company.SaleId = SalesMan.SaleId ;AND Description LIKE %TCL%以上查询中 ,用户输入一字符串以便在备注字段(Description) 中作匹配查找 .查询求出的是包含该字符串的所有公司的住处SQL 和字母大小写SQL 中是区分字母大小写的 ,为使
12、查询结果有效 ,要注意区分查询条件中的大小写.即表中的内容是大写的查询时必须将它们转换为大写 .若表中内容是大小写混杂的 ,则以下 Select 语句将难以返回全部结果 :Select CompanyId ;From Company ;Where CompanyId = ACME以上查询只返回名为 ACME 的记录 ,对于 CompanyId 为 Acme 的记录则查不到 ,因此安全的方法是用UPPER() 函数将所有字符串都转换为大写 .以下是正确的查询 :Select CompanyId ;From Company ;Where UPPER(CompanyId) = ACMESQL 和索引
13、WHERE 条件可用 Rushmore 和索引加速查找 .SQL 可用任何类型的索引 :结构化的 .CDX ,外部的 .CDX 及外部的 .IDX. 若要使 SQL 使用外部索引 ,必须在执行 Select 之前将其打开 ,如以下语句所示Use Sales INDEX idxfile,external cdxfileSQL 可以以同样的方式作为标准过程代码使用 Rushmore. 这时选择条件必须是可优化的 ,即选择表达式必 须与建立索引的表达式精确匹配 .用 Order By 子句对结果排序由于 SQL 优化器是按它认为的最佳方案去存取数据,因些查询结果中的记录顺序是动态不定的.许多应用程序
14、需要查询结果是按一个或多个字段排好序的.为此可用 ORDER BY 子句.ORDER BY 子句可以包含 Select 子句中一样多的字段 .例如 :Select Company,State,CompanyId ;From Client ;Where State IN(NY,NJ,PA,CA) ;Order By State,Company在以上查询中 ,按所在州及公司名称顺序给出结果.缺省情况下 ,记录是升序排字段 ,也可用 DESCENDING 来说明按降序排序 .当然也可以升降序并用 ,例如 :Select Company,State,CompanyId,SaleNo ;From Com
15、pany,Sales ;Where Company.SaleId = SalesMan.SaleId ;AND State IN(NY,NJ,PA,CA) ;ORDER BY State,Company,SaleNo DESCENDING以上查询结果首先按州及公司名称升序排字段,然后按SaleNo降序排序.由于排序是对查询结果的排序,因此Order By 子句中的字段必须是 Select子句中出现的字段.另外,Order By子句允许用位标号给出排序字段,这些位标号是指 Select子句中出现的序号例如上一个查 询可以写为:Select Compa ny ,State,Compa ny ld,
16、SaleNo ;From Compa ny ,Sales ;Where Compa ny.Saleld = SalesMa n.Saleld ;AND State IN(NY,NJ,PA,CA);ORDER BY 2,1,3 DESCENDING当Select子句包含了用户定义函数或FoxPro函数(如 UPPER()和LEFT()时,用位标号来给出排序字段显得十分方便.列函数在Select子句中可以用SQL提供的五个列函数,如下表所示:SQL的列函数函数描述AVG(字段名)求出指定字段上的平均值,只适用于数值型的字段SUM(字段名)求出指定字段上的和,只适用于数值型的字段MIN(字段名)求出
17、指定字段上的最小值,字段可以是数值型,字符型或日期型MAX(字段名)求出指定字段上的最大值,字段可以是数值型,字符型或日期型COUNT(字段名)求出指定字段上的值的出现个数,可以用COUNT(*)求出记录数所有列函数的结果都是单值关于列函数,别有以下需要注意的地方:列函数中的 DISTINCT可以在任一个列函数中(除了 MIN()和MAX()使用DISTINCT,这样在列函数的求值中将不计重复值例如:SELECT AVG(DISTINCT SalesPrice);FROM Sales在以上查询中,求出商品的销售单价,对于重复的SalesPrice,只计算一次注意在Select子句中只能使用一次
18、DISTINCT .以下查询是不正确的:SELECT DISTINCT AVG(DISTINCT SalesPrice),SalesMan ;FROM Sales还有一点要注意的是,在 COUNT() 函数中,*不能与 DISTINCT 连用(如 COUNT(DISTINCT *), 若在COUNT()中使用DISTINCT,需给出字段名列函数的嵌套以下查询是列函数嵌套的情况Select SUM(AVG(SalesPrice),SalesMan ;From Sales ;Group By Product_ID该查询是想求出每一产品的平均单价的和,但在运行时FoxPro会给出如下错误文件AVG.
19、prg 不存在这说明列函数是不能嵌套使用的例一:人员资料表ryb,内容如下:科室姓名职称政治面貌办公室awfw助工党员通讯科wafawe咼丄党员机械科afawe技术员团员财务科2wraw无无人事科afwe工程师无,以下列表的形式打印出来现要统计每个科室各有几名技术员、助工、工程师、高工、党员、团员科室技术员助工工程师咼工党员团员财务科223343命令如下:Select 科室 ,;sum(iif( 职称= 技术员,1,0), ;sum(iif( 职称=; 助工,1,0), ;sum(iif( 职称 = 工程师 ,1,0), ;sum(iif( 职称= 高工,1,0), ;sum(iif( 政治面
20、貌 = 党员 ,1,0),;sum(iif( 政治面貌 = 团员 ,1,0) ; from ryb group by科室例二:表 recdbf性质分一般、重大、特大;日期要统计出某年的 12 个月内每个月每种性质的记录各有多少,若该月没有记录就为零。 结果:月份一般 重大 特大10 131212这跟上面那个例子有点不同,上例只是按表中科室来分类,而这里就不同,因为不是每个月都有案件的,但在报表里没有案件的月也要占一行。所以这里要建立一个辅助表 :tempyf(yf N(2), 内有十二个记录,值为 1 至 12 ,代表 1 12 月。我先是老规则:Select month( 日期 ),;iif
21、( 性质= 一般,1,0) as 一般,;iif( 性质= 重大,1,0) as 重大,;iif( 性质= 特大,1,0) as 特大 ;from recdbf ;where year( 日期 )=? 年份 ;into curs temp1再用 tempyf 左联接临时表 temp1 ,根据 tempyf.yf 分组统计。 但一看,结果好象不对,没有记录的月份不在结果当中,而且这两条 select 好象可以合而为一。 以上查询可以更简洁地使用以下命令 :SELECT tempyf.*,;SUM(IIF(ISNULL(recdbf. 日期) OR AT( 一般 ,recdbf. 性质)=0,0,
22、1) AS 一般 ,;SUM(IIF(ISNULL(recdbf. 日期) OR AT( 重大 ,recdbf. 性质)=0,0,1) AS 重大 ,;SUM(IIF(ISNULL(recdbf. 日期) OR AT( 特大 ,recdbf. 性质)=0,0,1) AS 特大 ;FROM tempyf LEFT OUTER JOIN recdbf ;ON tempyf.yf = MONTH(recdbf.日期 ) AND YEAR( 日期 ) = ?yy; & 注意这里, on 后面是可以加上其它条件的GROUP BY tempyf.yf在上例中 , yy 是指具体那一年,如果不指定的话,那就
23、是把表中所有的记录算在一起。而且如果要指定具体那一年的话,那这个 YEAR(日期)=?yy 的条件是不能放在 where 或者having 里的。以上查询的另一个有趣的地方是 :sum 命令是可以直接累加 iif 的结果,而且过滤条件从 where 移到 on 后会发生这么大的差别!在 where 时,是先联接统计后再过滤,结果把那些没有记录的月份也过滤掉了; 而在 on 是先过滤再联接、统计,过滤结果中虽然没有记录的月份也不在其中,但因是左联接,也一样会以 null 代替,但给 iif 中的 isnull 给变成了 0.注:其中那个 ON tempyf.yf = MONTH(recdbf.
24、日期) AND YEAR( 日期) = ?yy 在视图生成器中是不能直接 做的,而只能用 Create sql view as 以命令的方式生成。用 GROUP BY 求分组小计GROUP BY 的意思是按给定字段进行分组 ,所谓分组就是将一组类似的记录压缩成一个结果记录,这样 就可以完成基于一组记录的计算。 例如, 若想找到某一特定地区所有订货的总和, 不用单独查看所有的记录, 可以把来自相同地区的所有记录合成为一个记录,并获得来自该地区的所有订货的总和。例如,若想看到订单表中具有特定 ID 号的客户订货的金额总值,只需将具有相同 Customer ID 号的订货 记录合成为一个记录,同时寻
25、找订货总量即可。GROUP BY 和 DISTINCT 之间的选择如果在字段串列中没使用字段函数,则 group by 参数与关键字 distinct 的效果相同。不过使用 group by 参数的效果显然要比使用关键字 distinct 来得快,而且在字段串列中的字段数越多,速度的差距 会越大。如果在字段串列中使用字段函数且使用group by 参数,则仍会显示出多个数据记录。 但是如果于字段串列中使用字段且使用关键字 distinct ,则只有一个数据记录会显示出来。显然有字段时应使用 group by 参数。例子:1、 select name,max(salary) from test
26、group by name2、 select distct name,max(salary) from test结果:grouy bydistinctnamesalarynamesalarynamesalaryalex20alex90mary95alex10mary44alex50tom95alex 90alex 30tom 45tom55tom15tom95mary33mary44HAVING 子句的使用我们已经可以求分组小计 ,但另一问题是: 如何控制或筛选分组 ?这里不能用 WHERE 子句 ,因为它只能对 基表中的记录作筛选。而我们要筛选的是中间表的分组记录。HAVING 子句可用于控
27、制从中间表到最终结果的过滤。 虽然在 HAVING 子句中可以用任何合法的字段或表 达式 ,但一般是用列函数。原因是 HAVING 子句要跟在 GROUP BY 子句后使用 ,这意味着 SELECT 子句中 有列函数 ,例如 :SELECT SALE_NO,SUM(SALE_AMOUNT) AS AMOUNT ;FROM SALEITEM,SALES ;WHERE SALES. SALE_NO = SALEITEM. SALE_NO ;GROUP BY SALE_NO ;HAVING SUM(SALE_AMOUNT)1000以上查询求出销售金额超过 1000 元的销售单及金额。HAVING 子
28、句中的列函数不必与 SELECT 子句中的列函数相同 ,例如SELECT SALE_NO,SUM(SALE_AMOUNT) AS AMOUNT ;FROM SALEITEM,SALES ;WHERE SALES. SALE_NO = SALEITEM. SALE_NO ;GROUP BY SALE_NO ;HAVING AVG(SALE_AMOUNT)100此查询求出平均商品金额在 100 元以上的销售记录 ,结果中要求给出销售单的总金额。WHERE 和 HAVING 都为查询提供过滤条件 ,经常有人问哪一个要好些。答案是 ,为了获取更好的性能 ,应该 用 WHERE 子句来过滤一般表的记录
29、,而用 HAVING 过滤 GROUP BY 后的分组结果。另外 ,使用 HAVING 子句时容易犯的一个错误是 :SELECT * FROM SALES HAVING SALESMAN_ID =“ 001 ”虽然以上查询也可运行 ,但不能利用 RUSHMORE, 因此要比以下查询慢数百到数千倍 :SELECT * FROM SALES WHERE SALESMAN_ID =“001 ”示例:对于 HAVING 子句, select 的条件过滤的先后顺序是这样的:先对 join 中的 on 表达式进行过滤,再到 where ,中间结果出来后再用 having 进行过滤,最后才把结果显示出来。所
30、以说 having 是对 select 结 果的最后一次过滤。它与 where 的分别就是 where 能够事先把不要的数据过滤掉,这样 select 里头就having 这个不用处理那么多的数据。但有些数据事先不知道要不要过滤,要根据结果才能确定,这时才用事后诸葛亮。这里用例子来比较一下on 、 where 、 having 的不同之处表 recdbf 内容如下:日期 性质2000 年 7 月 3 日 特大2000 年 7 月 9 日 特大2000 年 9 月 3 日 特大1999 年 3 月 2 日 一般1999 年 3 月 4 日 一般2000 年 1 月 3 日 一般2000 年 2
31、月 1 日 一般2000 年 2 月 3 日 一般2000 年 3 月 4 日 一般2000 年 8 月 7 日 一般2000 年 11 月 2 日 一般1999 年 2 月 3 日 重大2000 年 2 月 3 日 重大2000 年 5 月 2 日 重大2000 年 8 月 9 日 重大还有一个 tempyf 的辅助表,记录 12 个月 yf123456789101112on 的命令如下SELECT tempyf.*,;SUM(IIF(ISNULL(recdbf.日期 ).OR.AT( 一般 ,recdbf.性质)=0,0,1) AS一般,SUM(IIF(ISNULL(recdbf.日期 )
32、.OR.AT( 重大 ,recdbf.性质)=0,0,1) AS重大,SUM(IIF(ISNULL(recdbf.日期 ).OR.AT( 特大 ,recdbf.性质)=0,0,1) AS特大;FROM tempyf LEFT OUTER JOIN recdbf ;ON tempyf.yf = MONTH(recdbf.日期 ).AND.YEAR(日期 ) = ?yy;GROUP BY tempyf.yf其中 yy=2000 ,表示统计2000 年的数据用 where 的命令如下:SELECT tempyf.*,;SUM(IIF(ISNULL(recdbf.日期 ).OR.AT( 一般 ,rec
33、dbf.性质)=0,0,1) AS一般,SUM(IIF(ISNULL(recdbf.日期 ).OR.AT( 重大 ,recdbf.性质)=0,0,1) AS重大,SUM(IIF(ISNULL(recdbf.日期 ).OR.AT( 特大 ,recdbf.性质)=0,0,1) AS特大;FROM tempyf LEFT OUTER JOIN recdbf ;ON tempyf.yf = MONTH(recdbf.日期 );GROUP BY tempyf.yf ;where YEAR( 日期 ) = ?yy& 注意,条件从on 移到这里来了用 having 的命令如下:SELECT tempyf.*
34、,;SUM(IIF(ISNULL(recdbf.日期 ).OR.AT( 一般 ,recdbf.性质)=0,0,1) AS一般,SUM(IIF(ISNULL(recdbf.日期 ).OR.AT( 重大 ,recdbf.性质)=0,0,1) AS重大,SUM(IIF(ISNULL(recdbf.日期 ).OR.AT( 特大 ,recdbf.性质)=0,0,1) AS特大;FROM tempyf LEFT OUTER JOIN recdbf ;ON tempyf.yf = MONTH(recdbf.GROUP BY tempyf.yf ;日期);& 注意,条件从 on 移到这里来了having YE
35、AR( 日期 ) = ?yy on 的结果如下,这是正确的YF123456789101112般121000010010重大010010010000特大000000201000特大00用 where 的结果如下:YF一般重大1102213578100101010020用 having 的结果如下:YF12578911般1200101重大0210100特大0002010以上查询有什么不同呢?去和它们进on 是把先把 recdbf 中不是 2000 年的记录过滤掉,剩下的就是 2000 年的了,再用 tempyf 行外联接,其结果可用select tempyf.*,recdbf. 日期 ;from
36、tempyf left join recdbf ;ON tempyf.yf = MONTH(recdbf.日期).AND.YEAR(日期)=?yy;GROUP BY tempyf.yf来查看,这个中间结果出来后,再用 isnull 把空值的记录变成 0 或 1 ,然后由 sum 去统计,结果就出来 了而 where 呢,1 、它是先把 tempyf 外联接 recdbf, 相当于select tempyf.*,recdbf.* ;from tempyf left join recdbf on tempyf.yf=mont(recdbf.日期 )2 、然后把不是 2000 的记录过滤掉,这里要注
37、意的是,如果某个月没有记录的话,那在第一个步骤后日期那里是 null 值,这当然不是 2000 的记录,所以就给这个条件给过滤出去了,所以下一步的 sum 之后就只剩下那有记录的那个月了,象4、6月等几个月。就没有 3、然后进行sum()再看 having1 、第一步和 where 一样,2、第二步不同, 它是先 sum() ,这里的 sum 可不管你是 1999 年还是 2000 的,先累加起来再说, 这时,1999 和 2000 年的 2 月份都有“重大”这个记录, sum 的结果是 2,这里用第三个步骤去分辨这个 2 之 中那个是 1999 年的,那个是 2000 的,这当然分不清啦,所
38、以也错了。3、根据步骤 2 来把 2000 的过滤出来。所以 on 、 where 、 having 这三个都可以加条件的子句中, on 是最先执行, where 次之, having 最后。 但有时候如果这先后顺序不影响中间结果的话,那最终结果是相同的。但因为on 是先把不符合条件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,按理说应该速度是最快的。根据上面的分析,可 以知道 where 也应该比 having 快点的,因为它过滤数据后才进行 sum ,所以 having 是最慢的。但也 不是说 having 没用,因为有时在步骤 3 还没出来都不知道那个记录才符合要求时,就要用
39、 having 了。 用 TOP 子句选择一定数量或一定百分比的记录TOP 子句用来限定结果集中返回的记录数 :结果集中的头 50 条记录TOP 50头 25%TOP 25 PERCENT在查询的结果集合中,如果只需要其中一定数量或百分比的记录,可以在“查询设计器”或“视图设计 器”中,使用“杂项”选项卡上的“列在前面的记录”属性设置数量或百分比,也可以在 SELECT - SQL 命 令中添加 TOP 子句。在 TOP 子句中,所允许的数值范围为 1 到 32767 ;如果使用的是百分数,则范围 为 0.001 到 99.99 。例如,如果要选择具有最高总订货量的前 10 位顾客,可以用 G
40、ROUP BY 指定 CUST_ID 字段,来显 示每个顾客的合计记录, 然后在 ORDER BY 子句中按照 ORDER_AMT 排序。 若要得到最高的前十个记录, 需要在 ORDER_AMT 上面指定降序排列,从而使具有最高订货量的顾客在结果中最先显示。如果使用升序 排列,结果记录则按照订货量由少到多的次序排列,那么在结果集合中选择的前几个记录实际上是订货量最 少的。SELECT TOP 10 *FROMtestdata!customer INNER JOIN testdata!orders ;ON Customer.cust_id = Orders.cust_id;GROUP BY Cu
41、stomer.cust_id;ORDER BY Orders.order_amt DESC查询结果的输出定向使用 SELECT - SQL 语句的各个子句,可以指定多种不同的输出目标来保存查询结果。若要将查询结果输出到使用子句独立的表INTO TABLE mytable数组INTO ARRAY aMyArray临时表INTO CURSOR mycursor活动窗口TO SCREEN浏览窗口如果没有指定其他目标,则用它作默认值。保存了查询结果之后,您就可以使用命令将存储的结果加以适当组织,以便显示或打印。将查询结果存储到表、数组或临时表中查询结果可以存储到表、数组或临时表中,以备它用,例如处理表
42、单以及打印报表和标签。如果只想暂时保存结果,则可将它们发送到数组或临时表中。若要永久保存结果,则应该将它发送到一个表中。若要指定一个表作为输出目标 ,用 SELECT-SQL 语句的 INTO 子句指定一个目标。面的示例演示了如何用一个 INTO 子句指定一个表:SELECT *FROM tastrade!customer ;WHERE customer.country = Canada ;INTO TABLE mytable若要指定一个数组作为目标 ,用 SELECT - SQL 语句的 INTO 子句指定一个目标。 下面的示例演示了如何用 INTO 子句指定一个数组。SELECT * ;F
43、ROM tastrade!customer ;WHERE customer.country = Canada ;INTO ARRAY aMyArray若要指定一个临时表作为目标 ,用 SELECT-SQL 语句的 INTO 子句指定一个目标。 以下示例演示了如何用 INTO 子句指定一个临时表。SELECT * ;FROM tastrade!customer ;WHERE customer.country = Canada ;INTO CURSOR mycursor复杂查询复杂查询是指需要多个 Select 语句来决定最后结果的查询。传统的讲,复杂查询包括子查询,自身连接和合并。Select
44、命令参数很多,功能也很强大,适当的使用一些技巧,可以使程序更洁练,运行速度更快。但如 果不是很强求速度的话,我认为太过复杂的命令对以后的维护工作带来困难。呵呵,有时我要理解自己写的 命令都有点困难, 实在是太复杂了。 以下内容是工在工作过程中摸索出来的一些小技巧, 希望对别人有帮助。子查询子查询有时又叫内部查询 (INNER QUERY), 是一个嵌入到另一个 SELECT 中的 SELECT 语句。一个包括子查询的语句通常情况下以以下几种形式出现 :WHERE 表达式 NOT IN ( 子查询 )WHERE 比较操作符 ANY|ALL ( 子查询 )WHERE NOT EXISTS ( 子查
45、询 )当需要从一个查询的结果来产生最终结果时,一般要使用子查询。使用子查询时有如下限制 :子查询的 SELECT 子句中只允许有一个字段名 ,除非是在子查询中使用 * 通配符。只能在主查询中使用 UNION 和 ORDER BY , 而不能在子查询中使用它们。子查询必须用括号括起来。子查询只能使用比较、包含、存在和量词等条件。子查询中的 WHERE 子句可引用主查询中的字段 ,这称为外部引用IN 和 NOT ININ 关键字用于决定一个特定值是否是内部查询所产生的结果列表值中的一个值。相反 ,NOT IN 决定了某个 特定值是否不存在于一个内部查询的结果集中。对包含条件 (IN 关键字 ),子
46、查询的结果可以是一组数值。例如,在 temp2 中列出所有包含在 temp1 中的记 录。例一temp1 记录数: 90112temp2 记录数 22528两表均按 name 建立索引, temp2 全部都是包含在 temp1 里的。用子查询:Select temp2.* ;from temp2 ;where name in (sele name from temp1)1.542 秒 (有索引 )4.596( 无索引 )用联接:select temp2.* ;from temp2 ;join temp1 ;on = 2.384 秒 (有索引 )5.658
47、( 无索引 )相关的时间都是有一秒左右。 这应该是因为子查询首先执行,它把 temp1 中的一部分 (name) 读入内存, 然后 temp1 再在其中进行比较;而联接则一开始就是读文件,所以就慢了一点。列出没有采购的公司:select company from customer ;where cno not in ;(select cno from invoices)在上例中 ,先用 IN 关键字进行过滤 ,当过滤的条件表达式 cno 未出现在 invoices. Cno 中时便被选择出来。 请注意 where 子句中的 NOT 关键字的用法 ,如果不用 NOT 关键字 ,则上面查询的作用就
48、是列出有采购的 公司。IN 查询中的子查询 ,匹配主查询的一个值。可得出一组值来检查包含关系。因此,当希望由 SQL 产生一组有效值 ,而不是由用户输入时 ,可用 IN 子查询的方式。 量词只适用于来子查询的 IN 谓词。 IN 谓词只是简单地判断外部查询的值是否与值表中的某一个值相等。 量词可扩展这一包含关系 ,它可用于任何有效的比较符 (如 , 等等)。量词可以是 ANY 、SOME 或 ALL。ANY|SOME列出 ytdsales 字段至少必须大于 offices 其中个 ytdsales 字段之值。select * from salesman ;where ytdsalesANY ;
49、(select ytdsales form offices)对于外部查询的每一值 ,若小于子查询结果的任一值 ,则条件为真。在条件满足后 ,即终止比较。ALL当子查询中的所有值都能符合外部条件的比较符时 ,ALL 返回真。若有一个不满足 ,则停止处理并返回假值。 列出 ytdsales 字段必须大于 salesman.ytdsales 字段的值。select * from offices ;where ytdsalesALL ;(select ytdsales from salesman)含有量词的查询经常引起混淆 ,因为出现的比较符常与要求中的相反。 最后 ,量词产生一个逻辑值而不是一个比
50、较值。EXISTS 和 NOT EXISTS子查询用 EXISTS 和 NOT EXISTS 测试来发现两个集合间是否有交叉功区别。EXISTS (如果元素同时属于两个集合时为真)NOT EXISTS ( 如果只有第一个集合包含了元素时为真)EXIST 关键字的含意是 :判定外查询记录的某些值是否在内查询表中存在。例如:列出没有采购的公司:select company from customer ;where cno not exists ;(select * ;& 用 exists 这里一定要用星号“”from invoices where o=o)对于 EXIST 关键字有两点要注意。首先
51、 ,含 EXIST 关键字的查询总是相关查询 :即 ,内查询必然引用外查询 的字段 (如上例中的 cno) 。这使但存在谓词的子查询相当慢,因因对于外查询的每一记录 ,子查询都要执行一遍。外查询中要处理的记录数越多 ,则查询执行时间越长。其次 ,EXIST 关键字的子查询是唯一允许用通配符的 * 的情况。由于结果只有真或假 ,对说明什么字段无 关紧要 ,因此可用通配符。实际中 ,存在谓词的子查询总是用 * 。存在谓词只是标准的带子查询 IN 谓词的特殊形式。一般来说 ,IN 谓词要快于存在谓词。目前在实际的 SQL SELECT 中,其所有子查询都处在同一级 ,都是作为主查询的子查询。这就是说
52、 ,仅可 在主查询的选择条件中使用子查询。自身连接当一个表中的信息要与同一表中其它信息相比较时,需要用到自身连接。 需要使用自身连接的有两种典型情况一种是表中有多对多关系 ,一种是表中有跨越时间段的信息。示例: 按业务员的销售额的高低顺序,显示每一个业务员的销售额,并伴随显示那些比他销售还多的业务员的 平均销售额。Select a.salesman,,a.ytdsales,AVG(b.ytdsales) as better ;from salesman A,salesman B ;& 这里把 salesman 打开两次,分别起个别名 A 和 Bwhere A.ytdsalesB.y
53、tdsales ;group by A.salesman ;order by A.ytdsales DESC相同于使用联接:Select a.salesman,,a.ytdsales,AVG(B.ytdsales) as better ;from salesman inner join salesman salesman_a ;on salesman.ytdsalessalesman.ytdsales ;group by ;order by salesman.dd desc注:自连接时必须注意以下事项:1 、同一来源数据库务必给予不同的别名;2 、位于 select 命令语句的字段串列中各个字段前都必须中上别名;3 、由于一旦自连接后即形成“多对多”的关联性连接,因此请小心设定 where 参数的连接条件。在一 个有 1 千个记录的表中,执行第一条命令要 188.261 秒
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 基于机器学习的缺失值估算方法在医疗数据中的应用
- 面向卫星物联网的切片资源调度研究
- 天然毛皮服装附件企业数字化转型与智慧升级战略研究报告
- 医学图书馆与资料数字化服务行业深度调研及发展战略咨询报告
- 基因检测自动化流水线行业跨境出海战略研究报告
- 柜子企业县域市场拓展与下沉战略研究报告
- 科技创新在体育产业的应用与发展
- 制药用自动检漏设备行业深度调研及发展战略咨询报告
- 2025年声学海流计合作协议书
- 书包企业县域市场拓展与下沉战略研究报告
- 工会经费列支范围及工会经费支出范围
- 成人高考课件
- 村委会会议签到表
- 哲学与人生全套课件146P
- 中考物理复习交流
- 敬老院设备采购投标方案(技术方案)
- 充电桩采购安装售后服务方案
- 《旅行社条例》和《旅行社管理条例》对比解读
- 柳宗元抑郁而坚贞的一生
- 乡镇人大代表选举结果情况报告单
- BOPP双向拉伸薄膜及胶带生产项目环境影响报告
评论
0/150
提交评论