本文介绍如何用 AND 和 OR 操作符组合成 WHERE 子句以建立功能更强、更高级的搜索条件。我们还介绍了如何使用 NOT 和 IN 操作符。
在 如何使用 SQL WHERE 过滤返回的数据 中介绍的所有 WHERE 子句在过滤数据时使用的都是单一的条件。
为了进行更强的过滤控制,SQL 允许给出多个 WHERE 子句。这些子句有两种使用方式,即以 AND 子句或 OR 子句的方式使用。
操作符(operator)
用来联结或改变
WHERE子句中的子句的关键字,也称为逻辑操作符(logical operator)。
要通过不止一个列进行过滤,可以使用 AND 操作符给 WHERE 子句附加条件。下面的代码给出了一个例子:
SELECT prod_id, prod_price, prod_name
FROM Products
WHERE vend_id = 'DLL01' AND prod_price <= 4;
此 SQL 语句检索由供应商 DLL01 制造且价格小于等于 4 元的所有产品的名称和价格。
这条 SELECT 语句中的 WHERE 子句包含两个条件,用 AND 关键字联结在一起。AND 指示 DBMS 只返回满足所有给定条件的行。
如果某个产品由供应商 DLL01 制造,但价格高于 4 元,则不检索它。
类似地,如果产品价格小于 4 元,但不是由指定供应商制造的也不被检索。这条 SQL 语句产生的输出如下:
prod_id prod_price prod_name
------- ---------- --------------------
BNBG02 3.4900 Bird bean bag toy
BNBG01 3.4900 Fish bean bag toy
BNBG03 3.4900 Rabbit bean bag toy
AND
用在
WHERE子句中的关键字,用来指示检索满足所有给定条件的行。
这个例子只包含一个 AND 子句,因此只有两个过滤条件。可以增加多个过滤条件,每个条件间都要使用 AND 关键字。
说明:没有
ORDER BY子句为了节省空间,也为了减少你的输入,我在很多例子里省略了
ORDER BY子句。因此,你的输出完全有可能与本文中的输出不一致。虽然返回行的数量总是对的,但它们的顺序可能不同。
当然,如果你愿意也可以加上一个
ORDER BY子句,它应该放在WHERE子句之后。
OR 操作符与 AND 操作符正好相反,它指示 DBMS 检索匹配任一条件的行。
事实上,许多 DBMS 在 OR WHERE 子句的第一个条件得到满足的情况下,就不再计算第二个条件了(在第一个条件满足时,不管第二个条件是否满足,相应的行都将被检索出来)。
请看如下的 SELECT 语句:
SELECT prod_name, prod_price
FROM Products
WHERE vend_id = 'DLL01' OR vend_id = 'BRS01';
此 SQL 语句检索由任一个指定供应商制造的所有产品的产品名和价格。
OR 操作符告诉 DBMS 匹配任一条件而不是同时匹配两个条件。
如果这里使用的是 AND 操作符,则没有数据返回(因为会创建没有匹配行的 WHERE 子句)。
这条 SQL 语句产生的输出如下:
prod_name prod_price
------------------- ----------
Fish bean bag toy 3.4900
Bird bean bag toy 3.4900
Rabbit bean bag toy 3.4900
8 inch teddy bear 5.9900
12 inch teddy bear 8.9900
18 inch teddy bear 11.9900
Raggedy Ann 4.9900
OR
WHERE子句中使用的关键字,用来表示检索匹配任一给定条件的行。
WHERE 子句可以包含任意数目的 AND 和 OR 操作符。允许两者结合以进行复杂、高级的过滤。但是,组合 AND 和 OR 会带来了一个有趣的问题。为了说明这个问题,来看一个例子。
假如需要列出价格为 10 元及以上,且由 DLL01 或 BRS01 制造的所有产品。下面的 SELECT 语句使用组合的 AND 和 OR 操作符建立了一个 WHERE 子句:
SELECT prod_name, prod_price
FROM Products
WHERE vend_id = 'DLL01' OR vend_id = 'BRS01'
AND prod_price >= 10;
输出:
prod_name prod_price
------------------- ----------
Fish bean bag toy 3.4900
Bird bean bag toy 3.4900
Rabbit bean bag toy 3.4900
18 inch teddy bear 11.9900
Raggedy Ann 4.9900
请看上面的结果。返回的行中有 4 行价格小于 10 美元,显然,返回的行未按预期的进行过滤。
为什么会这样呢?原因在于求值的顺序。
SQL(像多数语言一样)在处理 OR 操作符前,优先处理 AND 操作符。
当 SQL 看到上述 WHERE 子句时,它理解为:由供应商 BRS01 制造的价格为 10 元以上的所有产品,以及由供应商 DLL01 制造的所有产品,而不管其价格如何。
换句话说,由于 AND 在求值过程中优先级更高,操作符被错误地组合了。
此问题的解决方法是使用圆括号对操作符进行明确分组。请看下面的 SELECT 语句及输出:
SELECT prod_name, prod_price
FROM Products
WHERE (vend_id = 'DLL01' OR vend_id = 'BRS01')
AND prod_price >= 10;
输出:
prod_name prod_price
------------------- ----------
18 inch teddy bear 11.9900
这条 SELECT 语句与前一条的唯一差别是,将前两个条件用圆括号括了起来。
因为圆括号具有比 AND 或 OR 操作符更高的优先级,所以 DBMS 首先过滤圆括号内的 OR 条件。
这时,SQL 语句变成了选择由供应商 DLL01 或 BRS01 制造的且价格在 10 元及以上的所有产品,这正是我们希望的结果。
提示:在
WHERE子句中使用圆括号任何时候使用具有
AND和OR操作符的WHERE子句,都应该使用圆括号明确地分组操作符。不要过分依赖默认求值顺序,即使它确实如你希望的那样。使用圆括号没有什么坏处,它能消除歧义。
IN 操作符用来指定条件范围,范围中的每个条件都可以进行匹配。IN 取一组由逗号分隔、括在圆括号中的合法值。下面的例子说明了这个操作符。
SELECT prod_name, prod_price
FROM Products
WHERE vend_id IN ('DLL01','BRS01')
ORDER BY prod_name;
输出:
prod_name prod_price
------------------- ----------
12 inch teddy bear 8.9900
18 inch teddy bear 11.9900
8 inch teddy bear 5.9900
Bird bean bag toy 3.4900
Fish bean bag toy 3.4900
Rabbit bean bag toy 3.4900
Raggedy Ann 4.9900
此 SELECT 语句检索由供应商 DLL01 和 BRS01 制造的所有产品。IN 操作符后跟由逗号分隔的合法值,这些值必须括在圆括号中。
你可能会猜测 IN 操作符完成了与 OR 相同的功能,恭喜你猜对了!下面的 SQL 语句完成与上面的例子相同的工作。
SELECT prod_name, prod_price
FROM Products
WHERE vend_id = 'DLL01' OR vend_id = 'BRS01'
ORDER BY prod_name;
输出:
prod_name prod_price
------------------- ----------
12 inch teddy bear 8.9900
18 inch teddy bear 11.9900
8 inch teddy bear 5.9900
Bird bean bag toy 3.4900
Fish bean bag toy 3.4900
Rabbit bean bag toy 3.4900
Raggedy Ann 4.9900
为什么要使用 IN 操作符?其优点如下。
IN 操作符的语法更清楚,更直观。AND 和 OR 操作符组合使用 IN 时,求值顺序更容易管理。IN 操作符一般比一组 OR 操作符执行得更快(在上面这个合法选项很少的例子中,你看不出性能差异)。IN 的最大优点是可以包含其他 SELECT 语句,能够更动态地建立 WHERE 子句。SQL 如何使用子查询 对此进行详细介绍。IN
WHERE子句中用来指定要匹配值的清单的关键字,功能与OR相当。
WHERE 子句中的 NOT 操作符有且只有一个功能,那就是否定其后所跟的任何条件。因为 NOT 从不单独使用(它总是与其他操作符一起使用),所以它的语法与其他操作符有所不同。
NOT 关键字可以用在要过滤的列前,而不仅是在其后。
NOT
WHERE子句中用来否定其后条件的关键字。
下面的例子说明 NOT 的用法。为了列出除 DLL01 之外的所有供应商制造的产品,可编写如下的代码。
SELECT prod_name
FROM Products
WHERE NOT vend_id = 'DLL01'
ORDER BY prod_name;
输出:
prod_name
------------------
12 inch teddy bear
18 inch teddy bear
8 inch teddy bear
King doll
Queen doll
这里的 NOT 否定跟在其后的条件,因此,DBMS 不是匹配 vend_id 为 DLL01,而是匹配非 DLL01 之外的所有东西。
上面的例子也可以使用 <> 操作符来完成,如下所示。
SELECT prod_name
FROM Products
WHERE vend_id <> 'DLL01'
ORDER BY prod_name;
输出:
prod_name
------------------
12 inch teddy bear
18 inch teddy bear
8 inch teddy bear
King doll
Queen doll
为什么使用 NOT?对于这里的这种简单的 WHERE 子句,使用 NOT 确实没有什么优势。但在更复杂的子句中,NOT 是非常有用的。
例如,在与 IN 操作符联合使用时,NOT 可以非常简单地找出与条件列表不匹配的行。
说明:MariaDB 中的
NOTMariaDB 支持使用
NOT否定IN、BETWEEN和EXISTS子句。大多数 DBMS 允许使用NOT否定任何条件。
本文介绍了如何用 AND 和 OR 操作符组合成 WHERE 子句以建立功能更强、更高级的搜索条件。还介绍了如何明确地管理求值顺序,以及如何使用 NOT 和 IN 操作符。
原文链接:https://www.developerastrid.com/sql/sql-and-or-in-not/
(完)
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
这似乎应该有一个直截了当的答案,但在Google上花了很多时间,所以我找不到它。这可能是缺少正确关键字的情况。在我的RoR应用程序中,我有几个模型共享一种特定类型的字符串属性,该属性具有特殊验证和其他功能。我能想到的最接近的类似示例是表示URL的字符串。这会导致模型中出现大量重复(甚至单元测试中会出现更多重复),但我不确定如何让它更DRY。我能想到几个可能的方向...按照“validates_url_format_of”插件,但这只会让验证干给这个特殊的字符串它自己的模型,但这看起来很像重溶液为这个特殊的字符串创建一个ruby类,但是我如何得到ActiveRecord关联这个类模型
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits