文档库 最新最全的文档下载
当前位置:文档库 › vfpSQL查询

vfpSQL查询

Visual FoxPro中的SQL Select查询

张初康(康康) 任明汉(RMH)

简介 (2)

基本的SQL Select (2)

From 子句 (2)

Select 子句 (2)

SQL 和用户自定义函数 (3)

Select 子句中的关键字和其它子句 (3)

Select 子句中的通配符 (3)

字段别名(AS) (4)

用DISTINCT 消去重复的记录 (4)

用WHERE 子句说明选择记录的条件 (4)

选择条件 (4)

连接条件 (4)

SQL 和宏 (4)

SQL 和字母大小写 (5)

SQL 和索引 (5)

用Order By 子句对结果排序 (5)

列函数 (6)

SQL 的列函数 (6)

列函数中的DISTINCT (7)

列函数的嵌套 (7)

用GROUP BY 求分组小计 (9)

GROUP BY 和DISTINCT 之间的选择 (9)

HAVING 子句的使用 (10)

用TOP 子句选择一定数量或一定百分比的记录 (13)

查询结果的输出定向 (14)

复杂查询 (15)

子查询 (15)

带子查询的IN 谓词和量词 (15)

ANY|SOME (16)

ALL (16)

EXISTS (17)

自身连接 (17)

合并 (18)

示例一.快速排名次 (20)

示例二.选择重复的记录 (20)

外连接 (21)

什么是外连接? (21)

用右外连接(Right Outer Join)选择记录 (22)

用左外连接(Left Outer Join)选择记录 (22)

用完全外连接(Full Outer Join)选择记录 (23)

用内连接加外连接选择记录 (24)

用内连接(Inner Join)选择记录 (25)

用嵌套的连接(Nested Join)选择记录 (25)

Visual FoxPro 5.0 中的新的FROM/JOIN 语法 (26)

为了更加清晰 (27)

用SQL Select 生成视图 (29)

注意事项 (30)

结束语 (30)

简介

SQL Select 命令是自FoxPro 2.5 以来实现的嵌入式SQL。一条合理的SQL Select 命令对于数据的查询速度要远远快于FoxPro 的过程性代码。ANSI/ISO 标准定义了SQL Select 各子句的实现方式,因此FoxPro 中写的SQL 查询可以方便地移植到其它平台。自FoxPro 2.5 以来,FoxPro 的内嵌式SQL Select 命令的功能一直在增强。目前的FoxPro SQL Select 命令支持空值(NULL),子查询,自身连接,合并,外连接等。本文将探讨如何利用SQL Select 的强大功能和灵活性来减轻应用程序的开发工作量和增加应用程序的性能。

基本的SQL Select

From 子句

在FROM 子句中指定要查询的表,若指定的表未打开,FoxPro 将自动打开指定的表,但在查询完成后,FoxPro并不自动关闭它所打开的表,若要在查询完成后关闭表,则必须以手动方式关闭它们。若在执行SQL SELECT 时,FROM 子句中指定的表已经打开,则FoxPro 以USE …AGAIN 的方式重新打开此表。

Select 子句

SELECT 子句中指定要查询的结果字段,这些结果可以是以下基本元素:

通配符*

表中的字段名

FoxPro 函数

SELECT 中可用的列函数

用户自定义函数

常数(常用于作为占位符)

以上各元素在SELECT子句中以逗号分开,例如:

SELECT 销售地区,销售部门,业务员;

FROM 销售表

若SELECT 子句中的字段名是唯一的,则不必在字段名前加别名修饰,SQL 能自动找到这些字段。若字段名是非唯一的(即同一字段名出现在FROM 子句中的两个或两个以上表中),FoxPro 返回以下错误信息:<字段>|<变量> 不唯一,必须加以限定

要纠正这一错误,用字段所在表的别名修饰该字段。

若在SELECT 子句中加入了FoxPro 函数,则意味着该语句不具备可移植性。

SQL 和用户自定义函数

FoxPro 支持在Select 子句中使用用户定义函数。但是由于在其它系统中不支持用户定义函数。因此在开发可能移植的系统时不要使用用户自定义函数。

Select 子句中的关键字和其它子句

Select 子句中的通配符

1、*(星号)

只能使用在字段串列参数中。代表来源数据库中所有的字段。如果select 是在二个以上的数据库中进行查询的,则要在号码前加上数据库别名。

* 是SQL 中的三个通配符之一(其它两个是? 和_ ,将在以后讨论),* 只能出现在Select 子句中,通配符前可以用别名修饰,在此情况下表示要查询指定工作区中的全部字段.同时还可以给出其它字段名.如:

Select销售表.*,客户表.客户代码, 客户表.客户名称;

FROM 销售表, 客户表;

WHERE销售表.客户代码=客户表.客户代码

2、%(百分号)

只能使用在Where 参数中,代表一连串任意字符类似于DOS 下的IT*.PRG 中的“*”。通常与运算符LIKE 搭配使用:

SELECT 客户名FROM客户表WHERE客户名LIKE “成都%公司”

以上查询选择所有公司名以”成都”开始,以”公司”结尾的客户,如:成都东方公司、成都西部发展公司等。

3、_(下划线)

也只能使用在where 参数中,代表一个任意字符。与DOS 下的DIR IT??.PRG中的”?”一样。例如_a% 表示第二个字符为a 的字串。通常与LIKE 搭配使用:

SELECT 客户名FROM客户表WHERE客户名LIKE “成都_公司”

以上查询选择类似于”成都分公司”, ”成都总公司”这样的公司名字。

另一种情况是文字数据中正好包含有星号、百分号、下划线(例如:软件部__业务组),此时可使用关键字ESCAPE 告诉SQL 哪一个字符是常数字符而非通配符。例如:

select company from customer

where company like"%\_%" escape "\"

此时escape 所指定字符(即\)后的那一个字段(此处为下划线_)将被视为常数字符而非通配符。

字段别名(AS)

FoxPro 提供了给Select 子句中的字段起别名的方法(这种方法不同于ANSI/ISO 标准):即可用AS 子句给出Select 子句中字段的别名,在多当需要直接浏览查询结果或查询结果中含有计算列时,该方法很有用处.例如:

SELECT “物资部” AS 部门,SUM(工资) AS 工资汇总;

FROM 工资表;

WHERE 部门编号= “0013”

用DISTINCT 消去重复的记录

SELECT 中的DISTINCT 关键字,可以消去查询结果中的重复行。例如要字段出所有购买了商的客户,可以用以下Select 语句:

SELECT DISTINCT客户名称;

FROM 销售细节表

注意,这里消去的重复记录是指SELECT 子句中的所有字段值均相等的记录.

当SQL 遇到DISTINCT 关键字时,即建立一个中间表。然后以SELECT 子句中的所有字段建立一个唯一索引,然后将索引用于中间表,并把索引中的记录放入查询结果中。这样就消去了重复记录,但是当SELECT 子句中的字段很多时,这一过程会很慢。

用WHERE 子句说明选择记录的条件

通常查询并不希望取出所有记录,而只是希望查出满足一定条件的记录,要做到这一点可以使用WHERE 子句。WHERE 子句把满足条件的记录作为查询结果。

选择条件

在WHERE 子句中可以包含多个选择条件,各条件间用AND 或OR 连接而构成较长的逻辑表达式。

连接条件

当一个查询涉及到多个表时,需要一个特殊类型的WHERE 条件,称为连接条件,连接条件建立了FROM 子句中的两表间的一对一或一对多的联系。

SQL 和宏

SELECT 子句中可以方便快捷地处理宏,在SELECT 语句中,宏替换只能替换一次,在以下查询之前,需要由用户给出表名和相应的表达式

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 中是区分字母大小写的,为使查询结果有效,要注意区分查询条件中的大小写.即表中的内容是大写的查询时必须将它们转换为大写.若表中内容是大小写混杂的,则以下Select 语句将难以返回全部结果:

Select CompanyId ;

From Company ;

Where CompanyId = "ACME"

以上查询只返回名为ACME 的记录,对于CompanyId 为Acme 的记录则查不到,因此安全的方法是用UPPER() 函数将所有字符串都转换为大写.以下是正确的查询:

Select CompanyId ;

From Company ;

Where UPPER(CompanyId) = "ACME"

SQL 和索引

WHERE 条件可用Rushmore 和索引加速查找.SQL 可用任何类型的索引:结构化的 .CDX ,外部的 .CDX 及外部的 .IDX.若要使SQL 使用外部索引,必须在执行Select 之前将其打开,如以下语句所示:

Use Sales INDEX idxfile,external cdxfile

SQL 可以以同样的方式作为标准过程代码使用Rushmore.这时选择条件必须是可优化的,即选择表达式必须与建立索引的表达式精确匹配.

用Order By 子句对结果排序

由于SQL 优化器是按它认为的最佳方案去存取数据,因些查询结果中的记录顺序是动态不定的.许多应用程序需要查询结果是按一个或多个字段排好序的.为此可用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 Company,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 Company,State,CompanyId,SaleNo ;

From Company,Sales ;

Where Company.SaleId = SalesMan.SaleId ;

AND State IN("NY","NJ","PA","CA") ;

ORDER BY 2,1,3 DESCENDING

当Select 子句包含了用户定义函数或FoxPro 函数(如UPPER() 和LEFT() )时,用位标号来给出排序字段显得十分方便.

列函数

在Select 子句中,可以用SQL 提供的五个列函数,如下表所示:

SQL 的列函数

函数描述

AVG(字段名) 求出指定字段上的平均值,只适用于数值型的字段

SUM(字段名) 求出指定字段上的和,只适用于数值型的字段

MIN(字段名) 求出指定字段上的最小值,字段可以是数值型,字符型或日期型

MAX(字段名) 求出指定字段上的最大值,字段可以是数值型,字符型或日期型

COUNT(字段名) 求出指定字段上的值的出现个数,可以用COUNT(*)求出记录数

所有列函数的结果都是单值

关于列函数,别有以下需要注意的地方:

列函数中的DISTINCT

可以在任一个列函数中(除了MIN() 和MAX())使用DISTINCT,这样在列函数的求值中将不计重复值.例如:

SELECT AVG(DISTINCT SalesPrice) ;

FROM Sales

在以上查询中,求出商品的销售单价,对于重复的SalesPrice,只计算一次.注意在Select 子句中只能使用一次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.prg" 不存在

这说明列函数是不能嵌套使用的.

例一:

人员资料表ryb,内容如下:

现要统计每个科室各有几名技术员、助工、工程师、高工、党员、团员,以下列表的形式打印出来

命令如下:

Select 科室,;

sum(iif(职称="技术员",1,0)), ;

sum(iif(职称=";助工",1,0)), ;

sum(iif(职称="工程师",1,0)), ;

sum(iif(职称="高工",1,0)), ;

sum(iif(政治面貌="党员",1,0)),;

sum(iif(政治面貌="团员",1,0)) ;

from ryb group by 科室

例二:

表recdbf

〖性质〗分一般、重大、特大;

〖日期〗

要统计出某年的12 个月内每个月每种性质的记录各有多少,若该月没有记录就为零。

结果:

月份一般重大特大

10 1 3

2212 3

......

1230 5

这跟上面那个例子有点不同,上例只是按表中科室来分类,而这里就不同,因为不是每个月都有案件的,但在报表里没有案件的月也要占一行。所以这里要建立一个辅助表:tempyf(yf N(2)),内有十二个记录,值为1 至12,代表1-12 月。

我先是老规则:

Select month(日期),;

iif(性质="一般",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,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 是指具体那一年,如果不指定的话,那就是把表中所有的记录算在一起。而且如果要指定具体那一年的话,那这个YEAR(日期) = ?yy 的条件是不能放在where 或者having 里的。

以上查询的另一个有趣的地方是:sum 命令是可以直接累加iif 的结果,而且过滤条件从where 移到on 后会发生这么大的差别!在where 时,是先联接统计后再过滤,结果把那些没有记录的月份也过滤掉了;而在on 是先过滤再联接、统计,过滤结果中虽然没有记录的月份也不在其中,但因是左联接,也一样会以null 代替,但给iif 中的isnull 给变成了0.

注:其中那个ON tempyf.yf = MONTH(recdbf.日期) AND YEAR(日期) = ?yy 在视图生成器中是不能直接做的,而只能用Create sql view as 以命令的方式生成。

用GROUP BY 求分组小计

GROUP BY 的意思是按给定字段进行分组,所谓分组就是将一组类似的记录压缩成一个结果记录,这样就可以完成基于一组记录的计算。例如,若想找到某一特定地区所有订货的总和,不用单独查看所有的记录,可以把来自相同地区的所有记录合成为一个记录,并获得来自该地区的所有订货的总和。

分组在与某些合计函数联合使用时效果最好,诸如SUM、COUNT、AVG 等等。

例如,若想看到订单表中具有特定ID 号的客户订货的金额总值,只需将具有相同Customer ID 号的订货记录合成为一个记录,同时寻找订货总量即可。

GROUP BY 和DISTINCT 之间的选择

如果在字段串列中没使用字段函数,则group by 参数与关键字distinct 的效果相同。不过使用group by 参数的效果显然要比使用关键字distinct 来得快,而且在字段串列中的字段数越多,速度的差距会越大。

如果在字段串列中使用字段函数且使用group by 参数,则仍会显示出多个数据记录。但是如果于字段串列中使用字段且使用关键字distinct,则只有一个数据记录会显示出来。显然有字段时应使用group by 参数。

例子:

1、select name,max(salary) from test group by name

2、select distct name,max(salary) from test

结果:

grouy by distinct

name salary name salary name salary

alex 20 alex 90 mary 95

alex 10 mary 44

alex 50 tom 95

alex 90

alex 30

tom 45

tom 55

tom 15

tom 95

mary 33

mary 44

HAVING 子句的使用

我们已经可以求分组小计,但另一问题是:如何控制或筛选分组?这里不能用WHERE 子句,因为它只能对基表中的记录作筛选。而我们要筛选的是中间表的分组记录。

HAVING 子句可用于控制从中间表到最终结果的过滤。虽然在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 子句中的列函数不必与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 子句来过滤一般表的记录,而用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 进行过滤,最后才把结果显示出来。所以说having 是对select 结果的最后一次过滤。它与where 的分别就是where 能够事先把不要的数据过滤掉,这样select 里头就不用处理那么多的数据。但有些数据事先不知道要不要过滤,要根据结果才能确定,这时才用having 这个事后诸葛亮。

这里用例子来比较一下on、where、having 的不同之处

表recdbf 内容如下:还有一个tempyf 的辅助表,记录12 个月

日期性质yf

2000年7月3日特大 1

2000年7月9日特大 2

2000年9月3日特大 3

1999年3月2日一般 4

1999年3月4日一般 5

2000年1月3日一般 6

2000年2月1日一般7

2000年2月3日一般8

2000年3月4日一般9

2000年8月7日一般10

2000年11月2日一般11

1999年2月3日重大12

2000年2月3日重大

2000年5月2日重大

2000年8月9日重大

on 的命令如下

SELECT tempyf.*,;

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.日期).AND.YEAR(日期) = ?yy;

GROUP BY tempyf.yf

其中yy=2000,表示统计2000 年的数据

用where 的命令如下:

SELECT tempyf.*,;

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 ;

where YEAR(日期) = ?yy && 注意,条件从on 移到这里来了

用having 的命令如下:

SELECT tempyf.*,;

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 ;

having YEAR(日期) = ?yy &&注意,条件从on 移到这里来了

on 的结果如下,这是正确的

YF 一般重大特大

1 1 0 0

2 2 1 0

3 1 0 0

4 0 0 0

5 0 1 0

6 0 0 0

7 0 0 2

8 1 1 0

9 0 0 1

10 0 0 0

11 1 0 0

12 0 0 0

用where 的结果如下:

YF 一般重大特大

1 1 0 0

2 2 1 0

3 1 0 0 5 0 1 0

7 0 0 2

8 1 1 0

用having 的结果如下:

YF 一般重大特大

1 1 0 0

2 2 2 0 5 0 1 0

7 0 0 2

8 1 1 0

9 0 0 1 11 1 0 0

以上查询有什么不同呢?

on 是把先把recdbf 中不是2000 年的记录过滤掉,剩下的就是2000 年的了,再用tempyf去和它们进行外联接,其结果可用

select tempyf.*,recdbf.日期;

from 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的记录过滤掉,这里要注意的是,如果某个月没有记录的话,那在第一个步骤后日期那里是null 值,这当然不是2000 的记录,所以就给这个条件给过滤出去了,所以下一步的sum 之后就只剩下那有记录的那个月了,象4、6 月等几个月。就没有

3、然后进行sum(……)

再看having

1、第一步和where 一样,

2、第二步不同,它是先sum(),这里的sum 可不管你是1999 年还是2000 的,先累加起来再说,这时,1999 和2000 年的2 月份都有“重大”这个记录,sum 的结果是2,这里用第三个步骤去分辨这个2 之中那个是1999 年的,那个是2000 的,这当然分不清啦,所以也错了。

3、根据步骤2 来把2000 的过滤出来。

所以on、where、having 这三个都可以加条件的子句中,on 是最先执行,where 次之,having 最后。但有时候如果这先后顺序不影响中间结果的话,那最终结果是相同的。但因为on 是先把不符合条件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,按理说应该速度是最快的。根据上面的分析,可以知道where 也应该比having 快点的,因为它过滤数据后才进行sum,所以having 是最慢的。但也不是说having没用,因为有时在步骤3还没出来都不知道那个记录才符合要求时,就要用having了。

用TOP 子句选择一定数量或一定百分比的记录

TOP 子句用来限定结果集中返回的记录数:

●结果集中的头50 条记录

TOP 50

●头25%

TOP 25 PERCENT

在查询的结果集合中,如果只需要其中一定数量或百分比的记录,可以在“查询设计器”或“视图设计器”中,使用“杂项”选项卡上的“列在前面的记录”属性设置数量或百分比,也可以在SELECT - SQL 命令中添加TOP 子句。在TOP 子句中,所允许的数值范围为1 到32767;如果使用的是百分数,则范围为0.001 到99.99。

例如,如果要选择具有最高总订货量的前10位顾客,可以用GROUP BY 指定CUST_ID 字段,来显示每个顾客的合计记录,然后在ORDER BY 子句中按照ORDER_AMT 排序。若要得到最高的前十个记录,需要在ORDER_AMT 上面指定降序排列,从而使具有最高订货量的顾客在结果中最先显示。如果使用升序排列,结果记录则按照订货量由少到多的次序排列,那么在结果集合中选择的前几个记录实际上是订货量最少的。

SELECT TOP 10 *;

FROM testdata!customer INNER JOIN testdata!orders ;

ON Customer.cust_id = Orders.cust_id;

GROUP BY Customer.cust_id;

ORDER BY Orders.order_amt DESC

查询结果的输出定向

使用SELECT - SQL 语句的各个子句,可以指定多种不同的输出目标来保存查询结果。

若要将查询结果输出到使用子句

独立的表INTO TABLE mytable

数组INTO ARRAY aMyArray

临时表INTO CURSOR mycursor

活动窗口TO SCREEN

浏览窗口如果没有指定其他目标,则用它作默认值。

保存了查询结果之后,您就可以使用命令将存储的结果加以适当组织,以便显示或打印。

将查询结果存储到表、数组或临时表中

查询结果可以存储到表、数组或临时表中,以备它用,例如处理表单以及打印报表和标签。如果只想暂时保存结果,则可将它们发送到数组或临时表中。若要永久保存结果,则应该将它发送到一个表中。

若要指定一个表作为输出目标,用SELECT-SQL 语句的INTO 子句指定一个目标。

下面的示例演示了如何用一个INTO 子句指定一个表:

SELECT * ;

FROM tastrade!customer ;

WHERE customer.country = "Canada" ;

INTO TABLE mytable

若要指定一个数组作为目标,用SELECT - SQL 语句的INTO 子句指定一个目标。

下面的示例演示了如何用INTO 子句指定一个数组。

SELECT * ;

FROM 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 命令参数很多,功能也很强大,适当的使用一些技巧,可以使程序更洁练,运行速度更快。但如果不是很强求速度的话,我认为太过复杂的命令对以后的维护工作带来困难。呵呵,有时我要理解自己写的命令都有点困难,实在是太复杂了。以下内容是工在工作过程中摸索出来的一些小技巧,希望对别人有帮助。

子查询

子查询有时又叫内部查询(INNER QUERY),是一个嵌入到另一个SELECT 中的SELECT 语句。

一个包括子查询的语句通常情况下以以下几种形式出现:

●WHERE 表达式[NOT] IN (子查询)

●WHERE 比较操作符[ANY|ALL] (子查询)

●WHERE [NOT] EXISTS (子查询)

当需要从一个查询的结果来产生最终结果时,一般要使用子查询。

使用子查询时有如下限制:

●子查询的SELECT 子句中只允许有一个字段名,除非是在子查询中使用* 通配符。

●只能在主查询中使用UNION 和ORDER BY ,而不能在子查询中使用它们。

●子查询必须用括号括起来。

●子查询只能使用比较、包含、存在和量词等条件。

●子查询中的WHERE 子句可引用主查询中的字段,这称为外部引用

IN 和NOT IN

IN 关键字用于决定一个特定值是否是内部查询所产生的结果列表值中的一个值。相反,NOT IN 决定了某个特定值是否不存在于一个内部查询的结果集中。

对包含条件(IN 关键字),子查询的结果可以是一组数值。例如,在temp2 中列出所有包含在temp1 中的记录。

例一

temp1 记录数:90112

temp2 记录数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 https://www.wendangku.net/doc/6616707722.html,=https://www.wendangku.net/doc/6616707722.html, 2.384秒(有索引) 5.658(无索引)

相关的时间都是有一秒左右。这应该是因为子查询首先执行,它把temp1 中的一部分(name)读入内存,然后temp1 再在其中进行比较;而联接则一开始就是读文件,所以就慢了一点。

例二

列出没有采购的公司:

select company from customer ;

where cno not in ;

(select cno from invoices)

在上例中,先用IN 关键字进行过滤,当过滤的条件表达式cno 未出现在invoices. Cno 中时便被选择出来。请注意where 子句中的NOT 关键字的用法,如果不用NOT 关键字,则上面查询的作用就是列出有采购的公司。

IN查询中的子查询,匹配主查询的一个值。可得出一组值来检查包含关系。

因此,当希望由SQL 产生一组有效值,而不是由用户输入时,可用IN 子查询的方式。

量词只适用于来子查询的IN 谓词。IN 谓词只是简单地判断外部查询的值是否与值表中的某一个值相等。量词可扩展这一包含关系,它可用于任何有效的比较符(如<,>,<>等等)。量词可以是ANY、SOME或ALL。

ANY|SOME

列出ytdsales 字段至少必须大于offices 其中个ytdsales 字段之值。

select * from salesman ;

where ytdsales>ANY ;

(select ytdsales form offices)

对于外部查询的每一值,若小于子查询结果的任一值,则条件为真。在条件满足后,即终止比较。

ALL

当子查询中的所有值都能符合外部条件的比较符时,ALL 返回真。若有一个不满足,则停止处理并返回假值。

列出ytdsales 字段必须大于salesman.ytdsales 字段的值。

select * from offices ;

where ytdsales>ALL ;

(select ytdsales from salesman)

含有量词的查询经常引起混淆,因为出现的比较符常与要求中的相反。最后,量词产生一个逻辑值而不是一个比较值。

EXISTS 和NOT EXISTS

子查询用EXISTS 和NOT EXISTS 测试来发现两个集合间是否有交叉功区别。

●EXISTS (如果元素同时属于两个集合时为真)

●NOT EXISTS (如果只有第一个集合包含了元素时为真)

EXIST关键字的含意是:判定外查询记录的某些值是否在内查询表中存在。例如:

列出没有采购的公司:

select company from customer ;

where cno not exists ;

(select * ; &&用exists这里一定要用星号“*”

from invoices where https://www.wendangku.net/doc/6616707722.html,o=https://www.wendangku.net/doc/6616707722.html,o)

对于EXIST关键字有两点要注意。首先,含EXIST关键字的查询总是相关查询:即,内查询必然引用外查询的字段(如上例中的cno)。这使但存在谓词的子查询相当慢,因因对于外查询的每一记录,子查询都要执行一遍。外查询中要处理的记录数越多,则查询执行时间越长。

其次,EXIST关键字的子查询是唯一允许用通配符的* 的情况。由于结果只有真或假,对说明什么字段无关紧要,因此可用通配符。实际中,存在谓词的子查询总是用* 。

存在谓词只是标准的带子查询IN 谓词的特殊形式。一般来说,IN 谓词要快于存在谓词。

目前在实际的SQL SELECT 中,其所有子查询都处在同一级,都是作为主查询的子查询。这就是说,仅可在主查询的选择条件中使用子查询。

自身连接

当一个表中的信息要与同一表中其它信息相比较时,需要用到自身连接。需要使用自身连接的有两种典型情况:一种是表中有多对多关系,一种是表中有跨越时间段的信息。

示例:

按业务员的销售额的高低顺序,显示每一个业务员的销售额,并伴随显示那些比他销售还多的业务员的平均销售额。

Select a.salesman,https://www.wendangku.net/doc/6616707722.html,,a.ytdsales,AVG(b.ytdsales) as better ;

from salesman A,salesman B ; &&这里把salesman打开两次,分别起个别名A和B

where A.ytdsales

group by A.salesman ;

order by A.ytdsales DESC

相同于使用联接:

Select a.salesman,https://www.wendangku.net/doc/6616707722.html,,a.ytdsales,AVG(B.ytdsales) as better ;

from salesman inner join salesman salesman_a ;

on salesman.ytdsales

group by https://www.wendangku.net/doc/6616707722.html, ;

order by salesman.dd desc

注:自连接时必须注意以下事项:

1、同一来源数据库务必给予不同的别名;

2、位于select 命令语句的字段串列中各个字段前都必须中上别名;

3、由于一旦自连接后即形成“多对多”的关联性连接,因此请小心设定where 参数的连接条件。在一个有1 千个记录的表中,执行第一条命令要188.261 秒,第二条命令要154.712 秒。而500 个记录时,第一条命令6.870 秒,第二条7.190 秒。虽然其中的数值有点不是很准确,但这不重要,只要知道不要随便使用这种方法就行了。

合并

与其它复杂查询不同,UNION 实际上是SELECT 语句上的子句。UNION 可以把来自两个或多个独立的SELECT 语句的信息合并为一个结果。在多数情况下是用UNION 把不相关表的信息合并起来。

UNION 有一个可选的子句ALL。与SELECT 语句不同,UNION 在默认情况下使用DISTINCT 消去结果中的重复记录。若要提高UNION 的速度,可用ALL 选项,这样免去UNION 消去重复记录的操作。

为什么UNION 在默认情况下要用DISTINCT ?这是由这一操作的特性决定的。当把两个不相关的表合并为一个结果时,同一记录可能存在于两个表中。

与SELECT 子句中的DISTINCT 一样,当使用DISTINCT 时会使UNION 的速度下降。因此, 如果基于对应用程序和表的了解,知道不会有重复记录或重复记录很少,这时可用ALL 来减少执行时间。

象子查询一样,UNION 要成功地执行,需遵循以下规则:

UNION 仅用于外查询, 不能用UNION 合并子查询。

使用UNION 的SELECT 子句必须有相同的字段数,相同的数据类型和相同的长度和精度,因为SQL 需把SELECT 语句的结果合并到一张表中。

为此SQL 使用第一个查询语句的SELECT 子句作为结果表的结构。若UNION 中的其它查询中的语句中的字段需在结果中,则必须出现在第一个查询的SELECT 子句中。若第一个SELECT 子句中的某字段不在其它查询语句中的表中,则该字段仍必须出现在这些查询语句的SELECT 子句中。

具体的例子如下:

在做生产管理时,原材料的每笔进货、领用、报废、退货情况都要详细记录,老板随时都可能了解一个月内每种原材料的各种情况。而编程时对数据的规范化后,必然要用好几个表来记录这四种操作。现在为了更快的求出结果,命令当然是越少越好。各个表的结构如下:

进货单jhd:jhdbh,jhrq

进货单明细jhdmx:jhdbh,yclbh,jhsl

领货单lhd:lhdbh,lhrq

领货单明细lhdmx:lhdbh,yclbh,lhsl

报废单bfd:bfdbh,bfrq

报废单明细bfdmx:bfdbh,yclbh,bfsl

退货单thd:thdbh,thrq

退货单明细thdmx:thdbh,yclbh,thsl

原材料表yclb:yclbh,yclmc,yclgg

查询日期范围放在begindata,enddata 里

为简便起见,只计算进货和退货,其它的照样做就行了。

Select yclbh,sum(jhsl) as jhsl,100000.00-100000.00 as thsl ;

From jhd join jhdmx ;

On jhd.jhdbh=jhdmx.jhdbh ;

Where between(jhd.jhrq,begindata,enddata) ;

Group by yclbh ;

Union ;

Select yclbh,100000.00-100000.00 ,sum(thsl) ;

From thd join thdmx ;

On thd.thdbh=thdmx.thdbh ;

Where between(thd.thrq,begindata,enddata) ;

Group by yclbh ;

Into cursor temp1

这样就会产生这样的结果

yclbh jhsl thsl

00001 3432 0 ┐

00002 4234 0 │这些是第一节select产生的

……┘

00002 0 3423 ┐

00003 0 4234 │这些是第二节select产生的

……┘

现在再对临时表temp1进行一次合计

select yclbh,sum(jhsl) as jhsl,sum(thsl) as thsl ;

from temp1 ;

group by yclbh ;

into cursor temp2

这个temp2就是结果了。

注1:如果要计算四种操作的话,就再加多两节select 就行了。

注2:在命令里使用100000.00-100000.00 这样奇怪的表达式是因为select 对那些要计算的、事先不能确定长度和类型的字段,它是根据运算过程中产生的第一条记录中,该字段的值来确定这个字段的类型和长度。所以以上那条命令,第一个记录中thsl 它是不知道长度是多少的,如果直接用0的话,那它就以为这个字段是数值型,长度是1,没有小数位。这当然不行,所以就要用这样一个表达式,来使它知道这个字段有9位长,小数位是2。

示例一.快速排名次

考试排名次,一般有个要求,就是如果有两个人并列第一,那跟着的就不是第二名,而是第三名,即第二名跳空了。所以我想出以下这个方法。

面对大数据量的排名次,若用scan...endscan 或do while 这种方法,时间会非常长。1048576 个记录中花了十多分钟才排了四十多万条记录。而我这种方法只需九十多秒(硬件:PII300(100*3),128M PC100,5.1G,VFP5.0),方法如下:

1。数据库dele:rec_id c(7) 升序;name c(10);fs n(4,1) 降序;rec_orde n(7),文件大小为29M,索引文件16M

2。建一个视图dele1

SELECT Dele.fs, Dele.rec_orde;

FROM dele;

ORDER BY Dele.fs DESC

3。根据视图dele1建立视图dele2

SELECT DISTINCT Dele1.fs, MIN(Dele1.rec_orde) AS rec_orde;

FROM dele1;

GROUP BY Dele1.fs

4。根据视图dele2和数据库dele建立视图dele3

SELECT Dele.rec_id, Dele.rec_orde, Dele2.rec_orde, Dele.fs;

FROM dele INNER JOIN dele2 Dele2 ;

ON Dele.fs = Dele2.fs;

ORDER BY Dele2.rec_orde

准备工作做好,现在可以排序了:

以上视图是事先做好的,不算入运行时间。

use dele1

replac rec_orde with recno() all

select 0

use dele3

replac rec_orde_a with rec_orde_b all

browse

示例二.选择重复的记录

SELECT * ;

hibernate HQL 模糊查询 3种方式

hibernate HQL 模糊查询 3种方式 以下是用 hibernate的HQL(面向对象的查询语言)实现模糊查询的3种方式,其中方式一是这三中方式中最理想的方式,至少方式一可以有效的防止由于查询条件中需要参数的增多导致的代码长度太长出现代码折行的情况(代码太长会给后期的维护和测试带来很大的不便)。但是还有比他更理想的方式,因为方式一在定义 strSQL时使用String ,这就势必会造成当变量过多时strSQL自身太长的问题。一个比较有效的改进办法就是将String 改进为StringBuffer来处理。 方法一: java 代码 public List listUncertainClasses(Object OId) throws Exception{ Session session=HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction();

String strSQL="from Classes as a where a.classno like :name"; Query query = session.createQuery(strSQL); query.setString("name", "%"+OId+"%"); List result=query.list(); for(int i=0;i Classes classes=(Classes)result.get(i); String classname=classes.getClassname(); String classno=classes.getClassno(); String specName=classes.getSpeciality().getName(); String departName=classes.getSpeciality().getDepartment().getName(); System.out.println(departName+"\t"+specName+"\t"+classname+"\t"+classno); } session.getTransaction().commit(); return result; } 方法二: java 代码 public List listUncertainClasses_01(Object OId) throws Exception{ Session session=HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); List result=session.createQuery("from Classes as a where a.classno like '%"+OId+"%'").list();

数据库模糊查询技术应用

龙源期刊网 https://www.wendangku.net/doc/6616707722.html, 数据库模糊查询技术应用 作者:刘晓慧 来源:《电脑知识与技术》2012年第02期 摘要:该文介绍了模糊集合理论相关知识及其在关系数据库查询中的应用,针对SQL语言的SELECT语句进行了模糊扩展。分析了简单模糊查询、复合模糊查询、将模糊查询转换为精确查询的方法并通过实例进行了验证。 关键词:关系数据库;模糊查询;隶属函数;阈值;匹配度 中图分类号:TP311文献标识码:A文章编号:1009-3044(2012)02-0255-03 The Application on Database Fuzzy Query Technology LIU Xiao-hui (Shenyang Institute of Engineering, Shenyang 110136, China) Abstract: This article describes the knowledge of fuzzy set theory and its application on relational database queries,Fuzzy extension of the SELECT statement in the SQL language. Analyze the method of simple fuzzy query, composite fuzzy queries, fuzzy queries into precise query and verified by examples. Key words: relational database; fuzzy query; membership function; threshold; matching degree 模糊集合的理论由美国加州大学著名教授L.A.Zadeh于1965年首先提出,主要用于研究 现实世界中一些模糊不清的问题,使之清晰化,这一理论在信息论、自动控制等领域的研究与应用也得到了迅速发展。而将模糊理论应用于数据库查询,主要是将模糊查询条件应用于传统的以二值逻辑和精确的数据工具为基础的数据库中,得到符合条件的结果,例如“在学生关系中查找计算机成绩较高的学生”,这里“较高”就是一个模糊的查询条件。 1模糊集合理论 1.1模糊集合 所谓在论域U上的一个模糊子集A是指:?u∈U,都有μA(u)∈[0,1]与之相对应,并且称为u属于模糊子集A的隶属度。即由映射:μA(u):U→[0,1] u→μA(u) 确定论域U的一个模糊子集A。 μA(u)=1,表示u完全属于A;μA(u)=0,表示u完全不属于A;0

C语言模糊查询程序实例

下面为大家介绍字符串模糊查询的C语言程序编写方法。首先说明一下模糊查询的分类。 举例说明:现在内存里面有三个字符串:“昨天的天气是雨天。”;“今天的天气是阴天,。;“明天的天气是晴天。”。现在要进行模糊查询,比如,我们输入“天气”,那么三个字符串都会输出到屏幕上;如果输入“今天的天气”,那么程序就会输出“今天的天气是阴天。”;但是如果我们输入“今天天气”,那么三个字符串都没有包含“今天天气”的字符串,也就没有输出,这是连续字符模糊查询的情况。也就述说,我们输入的字符串必须是目标字符串的一个连续部分。 然而一般情况下,连续字符模糊查询使用条件有限,我们更多需要的是间断字符模糊查询,比如上面的例子,在间断字符模糊查询的情况下,我们输入“今天天气”,或者输入“今天是”,程序就会输出“今天天气是阴天。”,也就是说,间断字符模糊查询不需要输入目标字符串的连续部分就可以找到目标字符串。 下面是模糊查询的C程序,程序功能包括连续和间断模糊查询。 //程序功能是模糊查询功能,包括连续模糊查询和间断模糊查询功能。 //在字符串str1中寻找str2字符串,如果找到,打印str1,否则打印no. #include #include int main(void){ char str1[20],str2[10]; //定义两个字符型数组 int i,j,k,flag; printf("Enter str1:"); scanf("%s",str1); printf("Enter str2:"); scanf("%s",str2); //分别在内存中存入两个字符串 i=strlen (str1); //i是字符串str1的长度 j=strlen (str2); //j是字符串str2的长度 flag=0; //flag的功能有二,一是计数,二是作为str2的字符元素编号。 for(k=0;k

多条件模糊匹配搜索--模糊查询

模糊匹配:多条件模糊匹配搜索 疯狂代码 https://www.wendangku.net/doc/6616707722.html,/ ?:http:/https://www.wendangku.net/doc/6616707722.html,/Asp/Article22620.html 转载于: https://www.wendangku.net/doc/6616707722.html,https://www.wendangku.net/doc/6616707722.html,/?65871/action_viewspace_itemid_4760.html 运行环境:IIS 脚本语言:VBscript 数据库:Access/SQL Server 数据库语言:SQL 1.概要: 不论是在论坛,还是新闻系统,或是下载系统等动态网站中,大家经常会看到搜索功能:搜索帖子,搜索用户,搜索软件(总之搜索关键字)等,本文则是介绍如何建立一个高效实用的,基于ASP的站内多值搜索。 本文面对的是“多条件模糊匹配搜索”,理解了多条件的,单一条件搜索也不过小菜一碟了。一般来讲,有两种方法进行多条件搜索:枚举法和递进法。搜索条件不太多时(n<=3),可使用枚举法,其语句频度为2的n次方,成指数增长,n为条件数。很明显,当条件增多以后,无论从程序的效率还是可实现性考虑都应采用递进法,其语句频度为n,成线性增长。需要指出的是,枚举法思路非常简单,一一判断条件是否为空,再按非空条件搜索,同时可以利用真值表技术来对付条件极多的情况(相信没人去干这种事,4条件时就已经要写16组语句了);递进法的思想方法较为巧妙,重在理解,其巧就巧在一是使用了标志位(flag),二是妙用SQL中字符串连接符&。下面以实例来讲解引擎的建立。 2.实例: 我们建立一通讯录查询引擎,数据库名为addressbook.mdb,表名为address,字段如下: ID Name Tel School 1 张 三 33333333 电子科技大学计算机系 2 李 四 44444444 四川大学生物系 3 王 二 22222222 西南交通大学建筑系 … … … … Web搜索界面如下: 姓名: 电话: 学校: 搜索按钮 采用枚举法的源程序如下: <%@ CODEPAGE = "936" %> '连接数据库 <%

mysql模糊查询的两种方法

本文将提供两种方法,第一种最土的方法:使用like语句第二种用全文索引,接下来将为你详细介绍 网上查了一下,有两种方法,第一种最土的方法:使用like语句第二种听涛哥说用全文索引,就在网上搜一下:如何在MySQL中获得更好的全文搜索结果 很多互联网应用程序都提供了全文搜索功能,用户可以使用一个词或者词语片断作为查询项目来定位匹配的记录。在后台,这些程序使用在一个SELECT 查询中的LIKE语句来执行这种查询,尽管这种方法可行,但对于全文查找而言,这是一种效率极端低下的方法,尤其在处理大量数据的时候。 mysql针对这一问题提供了一种基于内建的全文查找方式的解决方案。在此,开发者只需要简单地标记出需要全文查找的字段,然后使用特殊的MySQL方法在那些字段运行搜索,这不仅仅提高了性能和效率(因为MySQL对这些字段做了索引来优化搜索),而且实现了更高质量的搜索,因为MySQL使用自然语言来智能地对结果评级,以去掉不相关的项目。这篇文章将向您讲述在MySQL中如何进行全文搜索。 在进行数据库查询时,有完整查询和模糊查询之分。 SELECT 字段FROM 表WHERE 某字段Like 条件 其中关于条件,SQL提供了四种匹配模式: 1,%:表示任意0个或多个字符。可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示。 比如SELECT * FROM [user] WHERE u_name LIKE '%三%' 将会把u_name为“张三”,“张猫三”、“三脚猫”,“唐三藏”等等有“三”的记录全找出来。另外,如果需要找出u_name中既有“三”又有“猫”的记录,请使用and条件 SELECT * FROM [user] WHERE u_name LIKE '%三%' AND u_name LIKE '%猫%' 若使用SELECT * FROM [user] WHERE u_name LIKE '%三%猫%' 虽然能搜索出“三脚猫”,但不能搜索出符合条件的“张猫三”。 2,_:表示任意单个字符。匹配单个任意字符,它常用来限制表达式的字符长度语句: 比如SELECT * FROM [user] WHERE u_name LIKE '_三_' 只找出“唐三藏”这样u_name为三个字且中间一个字是“三”的; 再比如SELECT * FROM [user] WHERE u_name LIKE '三__'; 只找出“三脚猫”这样name为三个字且第一个字是“三”的; 3,[ ]:表示括号内所列字符中的一个(类似正则表达式)。指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个。 比如SELECT * FROM [user] WHERE u_name LIKE '[张李王]三' 将找出“张三”、“李三”、“王三”(而不是“张李王三”); 如[ ] 内有一系列字符(01234、abcde之类的)则可略写为“0-4”、“a-e” SELECT * FROM [user] WHERE u_name LIKE '老[1-9]' 将找出“老1”、“老2”、……、“老9”; 4,[^ ] :表示不在括号所列之内的单个字符。其取值和[] 相同,但它要求所匹配对象为指定字符以外的任一个字符。 比如SELECT * FROM [user] WHERE u_name LIKE '[^张李王]三' 将找出不姓“张”、“李”、“王”的“赵三”、“孙三”等; SELECT * FROM [user] WHERE u_name LIKE '老[^1-4]';

sql like 通配符 模糊查询技巧及特殊字符

sql like 通配符模糊查询技巧及特殊字符 1,SQL like对时间查询的处理方法 SQL数据表中有savetime(smalldatetime类型)字段,表中有两条记录,savetime 值为:2005-3-8 12:12:00和2005-6-6 14:02:02 我用下面语句什么也搜不出来 select * from soft where soft.savetime like'%2005-3-8%' SQL帮助中说: " 当搜索 datetime 值时,推荐使用 LIKE,因为 datetime 项可能包含各种日期部分。例如,如果将值 19981231 9:20 插入到名为 arrival_time 的列中,则子句 WHERE arrival_time = 9:20 将无法找到 9:20 字符串的精确匹配,因为 SQL Server 将其转换为 1900 年 1 月 1 日上午 9:20。然而,子句 WHERE arrival_time LIKE '%9:20%' 将找到匹配。" 后运行下面语句SELECT soft.*, CAST(soft.savetime AS varchar(20)) AS strdatetime, 发现 SQL把smalldatetime格试转成: 03 8 2005 12:12PM 我何用 like'%2005-3-8%'搜索到2005年3月8日所有的记录? select * from soft where datediff(d,soft.savetime,convert(datetime,'20050308',121))=0 ---- select * from soft where convert(char(10),soft.savetime,121)='20050308' 2, SQL对like 操作中的特殊字符处理方法: SQL Server查询过程中,单引号 ' 是特殊字符,所以在查询的时候要转换成双单引号 '' 。 在like操作还有以下特殊字符:下划线_,百分号%,方括号[],尖号^。 其用途如下: 下划线:用于代替一个任意字符(相当于正则表达式中的 ? ) 百分号:用于代替任意数目的任意字符(相当于正则表达式中的 * ) 方括号:用于转义(事实上只有左方括号用于转义,右方括号使用最近优先原则匹配最近的左方括号) 尖号:用于排除一些字符进行匹配(这个与正则表达式中的一样) 以下是一些匹配的举例,需要说明的是,只有like操作才有这些特殊字符,=操作是没有的。 a_b... a[_]b% a%b... a[%]b% a[b... a[[]b%

SQL多条件模糊查询解决方案(类似百度搜索)

SQL多条件模糊查询解决方案(类似百度搜索) SQL多条件模糊查询解决方案(类似百度搜索) 时间:2012-10-18 16:22:32 点击: 377 核心提示:前言:算法的基本特性在前几篇博客中已经做了详细的说明,经过不断的改进优化,到归仓的时候了,也就是说,该算法告一段落,不再更新。作为最终的解决方案,简要的总结一下算法特性,以方便读者参阅。l 目的:...前言:算法的基本特性在前几篇博客中已经做了详细的说明,经过不断的改进优化,到归仓的时候了,也就是说,该算法告一段落,不再更新。 作为最终的解决方案,简要的总结一下算法特性,以方便读者参阅。 l 目的:主要用于多条件模糊匹配。 l 贪婪特性:返回满足条件尽可能多的记录。 l 权重特性:为关键词分配权重,代表关键词的重要性,在不破坏贪婪特性的前提下,返回权重高的记录。 l 必要关键词指定特性:在不破坏贪婪特性和权

重特性的前提下,返回的结果中必须包含指定的关键词。 l 典型应用:问-答系统,例如百度提问、京东商品咨询。 经过分析,在最终的解决方案中,提供两个版本的算法,已经封装成存储过程和函数,直接导入数据库即可。 普通版本: l 描述:基于SQL的LIKE语句实现,使用简单,但受限于LIKE语句,不适合超大数据量处理。指定必要词会加快处理速度。 l 使用范围:万级别的数据量,数据量超过1万条,将导致运行缓慢。 l 使用方法:直接在查询分析器中运行脚本导入数据库即可。 l 调用示例:execute proc_Common_SuperLike'id','t_test','content','20','|','[i]|o|c' l 参数说明:id表的主键字段名称。t_test表名。content匹配内容字段名称。20选出20个记录(从顶至下匹配度越来越低)。|关键字的分隔符号。[i]|o|c一共有i,o,c 三个关键字,通过|分隔,其中i是必要词。

SQL最新模糊查询

在进行数据库查询时,有完整查询和模糊查询之分。 一般模糊查询语句如下: SELECT 字段 FROM 表 WHERE 某字段 Like 条件 其中关于条件,SQL提供了四种匹配模式: 1,% :表示任意0个或多个字符。可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示。 比如 SELECT * FROM [user] WHERE u_name LIKE '%三%' 将会把u_name为“张三”,“张猫三”、“三脚猫”,“唐三藏”等等有“三”的记录全找出来。 另外,如果需要找出u_name中既有“三”又有“猫”的记录,请使用and条件SELECT * FROM [user] WHERE u_name LIKE '%三%' AND u_name LIKE '%猫%' 若使用 SELECT * FROM [user] WHERE u_name LIKE '%三%猫%' 虽然能搜索出“三脚猫”,但不能搜索出符合条件的“张猫三”。 2,_ :表示任意单个字符。匹配单个任意字符,它常用来限制表达式的字符长度语句: 比如 SELECT * FROM [user] WHERE u_name LIKE '_三_' 只找出“唐三藏”这样u_name为三个字且中间一个字是“三”的; 再比如 SELECT * FROM [user] WHERE u_name LIKE '三__'; 只找出“三脚猫”这样name为三个字且第一个字是“三”的; 3,[ ] :表示括号内所列字符中的一个(类似正则表达式)。指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个。 比如 SELECT * FROM [user] WHERE u_name LIKE '[张李王]三' 将找出“张三”、“李三”、“王三”(而不是“张李王三”); 如 [ ] 内有一系列字符(01234、abcde之类的)则可略写为“0-4”、“a-e”

thinkphp实现like模糊查询方法

thinkphp实现like模糊查询方法 本文为大家讲解的是thinkphp实现like模糊查询的方法,以实例形式讲述了字符串形式及数组形式作为查询条件的like模糊查询实现方法,感兴趣的朋友可以参考下 本文实例讲述了thinkphp实现like模糊查询的方法,分享给大家供大家参考。具体实现方法如下: 目前使用thinkphp框架进行项目开发的人越来越多了,由于其封装性较好,导致了很多纯PHP开发的部分不易上手,本文实例即以like模糊查询为例对此加以说明。 这里主要通过举例来说明用法: ThinkPHP可以支持直接使用字符串作为查询条件,但是大多数情况推荐使用索引数组或者对象来作为查询条件,因为会更加安全。 一、使用字符串作为查询条件 这是最传统的方式,但是安全性不高, 例如: $User = M("User"); // 实例化User对象 $User->where('type=1 AND status=1')->select(); 最后生成的SQL语句是 SELECT * FROM think_user WHERE type=1 AND status=1 如果进行多字段查询,那么字段之间的默认逻辑关系是逻辑与 AND,但是用下面的规则可以更改默认的逻辑判断,通过使用 _logic 定义查询逻辑: $User = M("User"); // 实例化User对象 $condition['name'] = 'thinkphp'; $condition['account'] = 'thinkphp'; $condition['_logic'] = 'OR'; // 把查询条件传入查询方法 $User->where($condition)->select();

相关文档