SQL查询中否定问题的解决办法有哪些
lipiwang 2024-10-18 09:39 9 浏览 0 评论
本系列为@牛旦教育IT课堂在微头条上发布的内容,
为便于查阅,特辑录于此,是些常用和特殊的SQL用法。
前面篇章快线连接:
(四):常用SQL系列之:Null值、插入方式、默认值及复制等
(六):常用SQL系列之:删除方式、数据库、表及索引元信息查询等
(七):常用SQL系列之:表约束、最大/小值、非null数、平均值等
(八):常用SQL系列之:列值累计、占比、平均值以及日期运算等
SQL点滴(56):如何返回包含最大值和最小值的记录?
也就是说,查找表中所有的“两极”的记录,比如说返回员工中所有最高工资和最低工资的记录。我们来看看——
1)MySQL中的实现参考语句:
SELECT
ename,
salary
FROM
employee
WHERE
salary IN ( ( SELECT min( salary ) FROM employee ), ( SELECT max( salary ) FROM employee ) )
=====================
在Where子句中编写两个子查询,以返回最大值和最小值,作为过滤条件来查询即可,
上面的写法也适用PostgreSQL数据库。
------------------------------------
2)Oracle数据库中实现:
select ename ,salary
from (
select ename,salary,
min(salary) over() min_sal,
max(salary) over() max_sal
from employee
) x where salary in (min_sal,max_sal )
这里用函数 min over和max over,实现表中每行都可有最大和最小值,形成内联视图x,然后返回salary为min_sal或max_sal的行,实现查找的目的——返回只包含最大最小值的记录。
此例句也适用DB2和MS SQL。
SQL点滴(57):如何给查询结果进行等级划分?
也可以理解为类别划分,比如给员工表中的人员进行职位类型划分或薪资等级划分?
我们看看如何实现——
1)MySQL中:
SELECT
( SELECT count( DISTINCT b.job ) FROM employee b WHERE b.job <= a.job ) AS rnk,
a.job
FROM
employee a
ORDER BY1
这是个子查询来实现的,通用也适用PostgreSQL。
2)Oracle中,可以利用函数DENSE_RANK OVER来实现:
select dense_rank() over(order by job) rnk,job from employee
这个实现更简单。上面的写法也适合DB2和MS SQL。
若表中有薪资字段salary,考虑如何把工资进行等级分类呢?动手试试吧?
SQL点滴(58):关于数据查询时否定问题之一
比如学校选修改课中,没有选择某门课程的学生有哪些,哪些景点无人问津等。其实这句话的意思有2层,即啥课也没选的学生和没有选某课的学生。假设我们有一个学生表student(学生编号sno和姓名sname以及age),和选课表take(含学生编号sno和课程编号cno) 。
你可能会这样写SQL:
select * from student where sno in (select sno from take where cno !='cs110')。
如果不是数据巧合,这常会有错误:此结果并没回答“谁没有选CS110课程”之问,但回答了“谁选取了不是CS110课程”之问。正确的结果集因该包括没有选任何课的以及选取了除CS110之外的所有学生。那怎么实现呢?
1)MySQL中的示例写法:
select s.sno,sname,s.age from student s,left join take t on (s.sno=t.sno)
group by s.sno,s.sname,s.age
having max(case when t.cno = 'CS110' then 1 else 0 end) = 0
此写法也适合PostgreSQL。
2)SQL Server中写法(用到了case和Max Over函数):
select distinct sno,sname,age
from (
select s.sno,s.sname,s.age,
max(case when t.cno='CS110' then 1 else 0 end)
over (partition by s.sno,s.sname,s.age )as takes_CS110
from student s left join take t on (s.sno = t.sno)
) x where takes_CS110 = 0
这个也适合DB2.对于Oracle9及更高版也可以用此方法。
对于Oracle8及更早版,有其他方法,可用分组,参考如下:
select s.sno,s.sname,s.age from student s ,take t
where s.sno = t.sno (+) group by s.sno,s.sname,s.age
having max(case when t.cno = 'CS110' then 1 else 0 end )=0
其实这个问题,几个不同的数据库都用了相同技巧,即在结果集中创建一个“布尔”列,用于表示学生是否选取了CS110,如果选了返回1,否则为0.
作为一个小作业,你看看如何把中间结果也显示出来(包含1和0)?
SQL点滴(59):数据查询时否定问题之二。
查找选取CS112或选取CS114(但不是二者)的学生。也就是说若D和A同时选择了CS112和CS114,则应该排除二人;若S选择了CS113,但没选CS112或CS114,也应该排除。看看下面的语句:
select * from student
where sno in (select sno from take where cno !='CS112' and cno !='CS114' )
貌似解决所求,但结果是错误的。不符合我们上面要求描述。
由于学生可以选取多门课,因此这里的方法是为每个学生返回一行信息,指明了学生选取了CS112、CS114还是二者都选了。那么怎么实现,这里示例如下:
1)MySQL查询语句参考:
SELECT
s.sno,
s.sname,
s.age
FROM
student s,
take t
WHERE
s.sno = t.sno
GROUP BY
s.sno,
s.sname,
s.age
HAVING
sum( CASE WHEN t.cno IN ( 'CS112', 'CS114' ) THEN 1 ELSE 0 END ) =1
这个语句的下发也适合PostgreSQL。
2)Oracle里的语句参考:
select distinct sno,sname,age
from(
select s.sno,s.sname,s.age,
sum(case when t.cno in ('CS112','CS114') then 1 else 0 end )
over (partition by s.sno,s.sname,s.age) as takes_either_or
from student s, take t
where s.sno =t.sno
) x
where takes_either_or =1 .
重点提示:这个问题第一步是采用从表student到表take的内连接。这样,去掉没有选取任何课程的学生,下一步就是使用case表达式,指出学生是否选取了其中的一门课程。
错误语句和后面参考例句的结果如图所示。
SQL点滴(60):数据查询时否定问题之三
这个查询场景是这样的,即查找选取了CS112而未选取其他课程的学生。你可能这样写SQL语句,如下:
SELECTs.*
FROM student s,take t
WHERE s.sno = t.sno
AND t.cno = 'CS112'
这里可能C同学是唯一选择CS112而未选其他课程的学生,但结果却返回一堆数据,也包括选取其他课程的学生。这个问题换个说法“找到只选CS112课的同学”,就查“谁选了一门课,且是CS112的?”。虽然问题貌似简单,但逻辑关系要搞清楚,拆分了理解,问题想清楚了,接下来看看怎么实现。
1)MySQL的参考示例:
SELECTs.*
FROM student s, take t1, ( SELECT sno FROM take GROUP BY sno HAVING count( * ) = 1 ) t2
WHEREs.sno = t1.sno AND t1.sno = t2.sno AND t1.cno = 'CS112'
使用聚集函数count,确保查询的学生只有一门课。结果如图所示:
上面的写法也适合PostgreSQL数据库。
2)Oracle中的搞法:
SELECTsno,sname,age FROM
(
SELECT s.sno,s.sname,s.age t.cno,
count( t.cno ) over ( PARTITION BY s.sno, s.sname, s.age ) AS cnt
FROM student s, take t
WHERE s.sno = t.sno
) x WHERE cnt = 1 AND cno = 'CS112'
这里使用了count over窗口函数,以确保学生只选一门课程。
关于这个问题,主要编写一个查询回答“哪些学生只选了一门课程?”以及“哪个学生选了CS112课程”这两个问题,所以使用内联视图t2找到第一个问题,然后把内联视图链接到take表,并保留CS112的同学。这就可以了。
你试试有其他方法来实现吧。
好了,这个基本SQL系列就到这了。点个赞,分享出去吧。^_^
相关推荐
- 前端入门——css 网格轨道详细介绍
-
上篇前端入门——cssGrid网格基础知识整体大概介绍了cssgrid的基本概念及使用方法,本文将介绍创建网格容器时会发生什么?以及在网格容器上使用行、列属性如何定位元素。在本文中,将介绍:...
- Islands Architecture(孤岛架构)在携程新版首页的实践
-
一、项目背景2022,携程PC版首页终于迎来了首次改版,完成了用户体验与技术栈的全面升级。作为与用户连接的重要入口,旧版PC首页已经陪伴携程走过了22年,承担着重要使命的同时,也遇到了很多问题:维护/...
- HTML中script标签中的那些属性
-
HTML中的<script>标签详解在HTML中,<script>标签用于包含或引用JavaScript代码,是前端开发中不可或缺的一部分。通过合理使用<scrip...
- CSS 中各种居中你真的玩明白了么
-
页面布局中最常见的需求就是元素或者文字居中了,但是根据场景的不同,居中也有简单到复杂各种不同的实现方式,本篇就带大家一起了解下,各种场景下,该如何使用CSS实现居中前言页面布局中最常见的需求就是元...
- CSS样式更改——列表、表格和轮廓
-
上篇文章主要介绍了CSS样式更改篇中的字体设置Font&边框Border设置,这篇文章分享列表、表格和轮廓,一起来看看吧。1.列表List1).列表的类型<ulstyle='list-...
- 一文吃透 CSS Flex 布局
-
原文链接:一文吃透CSSFlex布局教学游戏这里有两个小游戏,可用来练习flex布局。塔防游戏送小青蛙回家Flexbox概述Flexbox布局也叫Flex布局,弹性盒子布局。它决定了...
- css实现多行文本的展开收起
-
背景在我们写需求时可能会遇到类似于这样的多行文本展开与收起的场景:那么,如何通过纯css实现这样的效果呢?实现的难点(1)位于多行文本右下角的展开收起按钮。(2)展开和收起两种状态的切换。(3)文本...
- css 垂直居中的几种实现方式
-
前言设计是带有主观色彩的,同样网页设计中的css一样让人摸不头脑。网上列举的实现方式一大把,或许在这里你都看到过,但既然来到这里我希望这篇能让你看有所收获,毕竟这也是前端面试的基础。实现方式备注:...
- WordPress固定链接设置
-
WordPress设置里的最后一项就是固定链接设置,固定链接设置是决定WordPress文章及静态页面URL的重要步骤,从站点的SEO角度来讲也是。固定链接设置决定网站URL,当页面数少的时候,可以一...
- 面试发愁!吃透 20 道 CSS 核心题,大厂 Offer 轻松拿
-
前端小伙伴们,是不是一想到面试里的CSS布局题就发愁?写代码时布局总是对不齐,面试官追问兼容性就卡壳,想跳槽却总被“多列等高”“响应式布局”这些问题难住——别担心!从今天起,咱们每天拆解一...
- 3种CSS清除浮动的方法
-
今天这篇文章给大家介绍3种CSS清除浮动的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。首先,这里就不讲为什么我们要清楚浮动,反正不清除浮动事多多。下面我就讲3种常用清除浮动的...
- 2025 年 CSS 终于要支持强大的自定义函数了?
-
大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!1.什么是CSS自定义属性CSS自...
- css3属性(transform)的一个css3动画小应用
-
闲言碎语不多讲,咱们说说css3的transform属性:先上效果:效果说明:当鼠标移到a标签的时候,从右上角滑出二维码。实现方法:HTML代码如下:需要说明的一点是,a链接的跳转需要用javasc...
- CSS基础知识(七)CSS背景
-
一、CSS背景属性1.背景颜色(background-color)属性值:transparent(透明的)或color(颜色)2.背景图片(background-image)属性值:none(没有)...
- CSS 水平居中方式二
-
<divid="parent"><!--定义子级元素--><divid="child">居中布局</div>...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- maven镜像 (69)
- undefined reference to (60)
- zip格式 (63)
- oracle over (62)
- date_format函数用法 (67)
- 在线代理服务器 (60)
- shell 字符串比较 (74)
- x509证书 (61)
- localhost (65)
- java.awt.headless (66)
- syn_sent (64)
- settings.xml (59)
- 弹出窗口 (56)
- applicationcontextaware (72)
- my.cnf (73)
- httpsession (62)
- pkcs7 (62)
- session cookie (63)
- java 生成uuid (58)
- could not initialize class (58)
- beanpropertyrowmapper (58)
- word空格下划线不显示 (73)
- jar文件 (60)
- jsp内置对象 (58)
- makefile编写规则 (58)