asp.net怎么实现按条件查询_MySQL之DQL数据查询语言

DQL数据查询语言

继MySQL的大致介绍后,我们来看看MySQL中的查询语句怎么写。

建库及导入数据

在这之前,如果我们还没有学习DML和DDL,我们就需要一些数据来帮助我们学习DQL,而这些数据如下:

db612253d811f5fdee274914684beead.png

dept(部门)表,里面的字段分别为部门编号、部门名称、位置

d33b832450027aba536fec4e4e39fe7e.png

emp(员工)表,里面的字段分别为员工编号、员工名称、职位、上级领导编号,雇佣日期,工资,补贴,部门编号

7f7c9348fb763646518cd8753954257d.png

salgrade(工资等级)表,里面的字段分别为等级,最低界限,最高界限

d23bbe612df3a57190d96e8e6c8591cf.png

以后我们都以这些数据来进行示例。

首先我们需要学会建库,建库的语句很简单:

create database 库名;

比如,我需要建一个名为ccb的库:

e7de279fb7e516e466dc3179a10babbd.gif

与之对应的删库为:

drop database 库名;

比如,我需要删除一个名为ccb的库:

a77a067ea1a8fbee9a0b5b5de99f34ef.gif

建完库后,我们就需要导入数据,这时候,我们需要一种扩展名为.sql的文件(这种文件我们称为sql脚本,里面存放大量的sql语句),文章中使用的表可以在公众号中发送【MySQL源文件】获取。之后用选中库后用以下的语句:

source sql文件;

将以上提到的三个表格导入到相应的库中。

2c70bc664017e0be744c8c901e49455b.gif

导入后用show tables;检查下是否成功导入了,如果有那三张表后,我们就可以开始来学DQL了。

17b9c401813256c452fdb99403897dfc.png

0c8a867e0c1e9f2b6f1e658bb64fd603.gif简单查询语句 0c8a867e0c1e9f2b6f1e658bb64fd603.gif

最基本的查询格式为:

select 

    字段名 [as 重命名字段名], 

    字段名 [as 重命名字段名], 

    ... 

from 

    表名;

[]里面的内容可以省略,我们可以选择我们需要的字段来查看数据,如:

a4897f4958feb2ffc91b7aa7f0e11f72.gif

从中我们还可以看出在SQL语句中不区分大小写。那[]里面是干什么的呢?其实是在输出时给某个字段重命名,如:

8159daba7e7df04c4367f59555af24b3.gif

当然,as是可以省略的:

8e3cfe47f557b82679d062e8373dee10.gif

*一般都是表示通配符,所以想看整个表的数据就用

select * from 表名;

如查询dept表中所有内容:

80f41be6a32b05f4615d31ed54ed48fc.gif

但用*的效率比较低,所以不建议使用。

0c8a867e0c1e9f2b6f1e658bb64fd603.gif条件查询语句 0c8a867e0c1e9f2b6f1e658bb64fd603.gif

格式为:

select 

    字段名 [as 重命名字段名], 

    字段名 [as 重命名字段名], 

    ... 

from 

    表名

where

    条件;

那么有哪些条件可用呢?

1.>、>=、

6bd2185b4839ad10fa3722ae1a76ce1f.gif

2.<>、!= 都表示不等于

6f9764053d87419f429eefccfe579c8d.gif

3. and or 并且,或者

47f677ce4d38a88fd8ea91a4763e7636.gif

6a8fdc6817a8527049c2e8f90cc09025.gif

从以上可以看出在MySQL中,字符串是用''括起来,那么能不能用""呢?

73f85c021598791b3a69d82b55a2f50f.png

答案是可以的,但因为''是所有数据库都支持的,""不是所有数据库都支持,所以在MySQL中我们一般都用''把字符串括起来。并且标准的sql语句要求字符串用''括起来

4.between...and... 在两者之间,是一个闭区间

ad06f0dd168e18644bd520e7888fbacf.gif

可以看出between and 和上面的>= and <=等价。

5.not 取反,和Java中的!取反一样,这里就不再演示

6、in、not in

ca83cad2ce48867ea88dbadf6233d586.gif

可以看出in和上面的or其实也差不多,括号里面放需要的取值。而not in就是不在那个集合里面的元素,也不再演示。

7、is null、 is not null 为空、不为空

543c916ebfcfefd10519d378665e0e6b.gif

在MySQL中,表示数据为空用NULL表示,那有时候我们需要找出为NULL的数据这时候就需要用到它。而is not null就是找出不为空的,也不演示。

8、like 后面跟一个字符串,可以用来进行模糊查询

其中,%表示匹配任意多的字符;而_表示匹配一个字符

254747307d830f9d6d0d823284f4db93.gif

327ba7c9279755d734c45ce97fd617bd.gif

而如果模糊搜索中需要%或者_的话,我们就需要用反斜杠来进行转义了,如:

'%\%%' 匹配包含%的文本

'%\_%' 匹配包含_的文本

对于条件查询,以上就是最常见的一些条件了。

上述提到了NULL这个为空的关键字,在这里,我们还需要知道的一点是在运算中,如果加进去了数据为空的单元格,那么计算的结果永远都是空的。比如:

a84793dd4adc01e4822d9c3e89eff0e5.gif

可以看到,工资加补贴应该都是有值的,但因为有数据为空的参与运算,所以结果还是为空。

6e77a89b2def6ceeb45998171364d70b.png 0c8a867e0c1e9f2b6f1e658bb64fd603.gif去重查询语句 0c8a867e0c1e9f2b6f1e658bb64fd603.gif

格式为:

select distinct

    字段名 [as 重命名字段名], 

    字段名 [as 重命名字段名], 

    ... 

from 

    表名;

可以看出,去重其实就是在select后面加distinct而已,如:

e53d06834cfee0996fb3428ea4ae9953.gif

而需要注意的是,distinct只能出现在字段的前面,并且查询多个字段去重时,多个字段相同时才去重。如:

47553c9bc83f4db492985902b9820e25.gif

0c8a867e0c1e9f2b6f1e658bb64fd603.gif排序查询语句 0c8a867e0c1e9f2b6f1e658bb64fd603.gif

格式为:

select 

    字段名 [as 重命名字段名], 

    字段名 [as 重命名字段名], 

    ... 

from 

    表名

order by

    字段名 [asc/desc],

    [字段名 [asc/desc],]

    ...;

其中asc表示升序:

35436c6f5fb7a7b85bfe102eb3b721cb.gif

desc表示降序:

78bb80bc566e9846251862bf2b37d9cc.gif

1、如果最后的asc/desc不写的话会怎么样?

ef5fd77de0f0f27c5383981eb6de9eec.gif

可以看出,默认的排序规则为升序。

2、可能我们在查询多个字段时,有多个排序规则。比如出现这种情况:在查询ENAME和SAL两个字段时,我想先通过SAL的降序排序,然后在相等的SAL中通过ENAME的降序排列,那么我们应该怎么写呢?

065fe4cc331372ba825e1be6bbd9899b.gif

只需要看哪个排序的优先级高,写在排序的前面就行

3、如果我们在select的时候,对表格重命名了,那么写重命名后的名字还能实现嘛?或者写重命名之前的名字还能实现吗?

6f11926683ca89665d506f836d9ca9af.gif

可以看出其实两者都是可以的。

4、最后,对于排序查询,还有一个可以取巧的地方,我们可以将以上的字段名改成字段在select后面出现的下标,也是可以达到同样的效果:

2259d43e5e0984856d18811c308df445.gif

以上我们用sal排序,sal在select后面的第三个位置出现,我们就可以写3来代替sal。

函数

对于MySQL,也有自己的一套常用的函数,感兴趣的读者可以去网上查看,这里就不再一一列举。这里拿常用的函数来说明。

多行处理函数

最常用的就是聚合函数了:

max,min,avg,sum,count。

顾名思义,我们通过字面意思可以知道上述函数的作用分别为:求最大值,求最小值,求平均值,求和,求记录条数。也叫做分组函数/多行处理函数

那么该如何使用呢?我们看一些简单的例子,如:求所有员工的工资总和:

bc863bf28bf2c1d738ee8ca2411983b2.gif

求所有员工最大工资:

41d787119dc754a148e90bc3cf146e11.gif

从上面的例子可以看出,分组函数有个特点就是多行输入,一行输出。而且自动忽略NULL(上述求和的时候有NULL值,但是最终结果不是NULL)。因此又引出了count(*)和count(字段)的区别:

c7579f4848ea33e1ef817d8b703bad5d.gif

可以看到,count(*)计算全部记录条数,而count(字段)计算该字段所有非空记录条数

再来个例子,求工资大于平均工资的员工,应该怎么写呢?是这样?

select 

    ename,sal 

from

    emp 

where 

    sal > avg(sal);

我们可以复制过去看看:

c3ca0ae8297773dbd35c86ef4670c7c5.gif

会发现报错了,为什么呢?等我们等下看完分组查询语句之后就知道了。

单行处理函数

有多行处理函数,就有单行处理函数,如ifnull函数,这种函数的特点是n行输入,n行输出

ifnull函数用法:传入两个参数,第一个传入字段,第二个表示如果这个字段的值为null就替换为指定的值。如:

b1d759cea72402253469c4c2827e3393.gif

可以看到,上面的ifnull就把comm为null的单元格都变为0了。

0c8a867e0c1e9f2b6f1e658bb64fd603.gif分组查询语句 0c8a867e0c1e9f2b6f1e658bb64fd603.gif

格式为:

select 

    字段名 [as 重命名字段名], 

    字段名 [as 重命名字段名], 

    ... 

from 

    表名

group by

    字段名    

having

    字段名;

通过字面意思也可以大致上知道group by就是指定按字段进行分组,而having其实就是在group by分组的基础上再次进行分组。例如:

找出每个职位的最高工资:

0d6fb83728cb871eea334f357bf76915.gif

找出每个职位最高工资大于1500的职位:

9335a1e8c5b613c4eafb723f1f15d9ca.gif

对于group by和having,具有这样的关系:有group by才有having!而且在严格的角度来说,在经过group by分组后,select之后所加的字段只能是分组函数和分组的字段。但在MySQL中,不满足这个条件是可以运行的,但是在其他数据库中就可能会报错了!

到这里,我们的DQL语句基本上都有了,它们之间可以相互组成形成更复杂的DQL语句,这里我们看下这个语句组合起来后的执行顺序:

5、select 

    ..

1、from

    ..

2、where

    ..

3、group by

    ..

4、having

    ..

6、order by

    ..;

可以看到,group by是在where语句之后执行的,而且分组函数是在group by语句之后执行的(和group by连用,没有group by时整个表数据自成一组)。因此,这就解释了上述那个分组函数最后一个例子报错的原因了,因为where语句先执行,如果where里面有分组函数,但因为分组函数又是在group by后执行的,所以就报错了!因此,分组函数不能在where中使用

最后,因为先走条件语句,之后再走分组语句,所以我们之后能先在where语句中排除一些数据的话,可以大大提高执行效率,还是以找出每个职位最高工资大于1500的职位为例:

select job, max(sal) maxsal from emp group by job having maxsal > 1500;

其实等价于:

select job, max(sal) maxsal from emp where sal > 1500 group by job;

3d02539221b6f54a95e91272deb2fa06.gif

看上面的运行时间是0.01s,而下面的为0.00s。可能现在还看不出区别,但以后就很重要了。

0c8a867e0c1e9f2b6f1e658bb64fd603.gif连接查询语句 0c8a867e0c1e9f2b6f1e658bb64fd603.gif

因为数据都放在同一张表的话会造成数据冗余,所以一般数据都是放在很多张表中的,而连接查询就是联合着其他表一起查询的语句。

连接查询有两种划分方式:

1、按年代划分:

    SQL92

    SQL99

2、按连接方式划分:

    内连接:等值连接、非等值连接、自连接

    外连接:左外连接、右外连接

    全连接(MySQL没有)

其中,SQL92支持内连接,而SQL99支持内连接和部分外连接。

在多表查询的时候会出现一种现象:笛卡尔积现象(简单说明就是比如两张表进行查询,表1有m行,表2有n行,结果集有m*n行,然后再进行筛选),造成这种现象的原因是因为连接查询中没有条件进行过滤,所以需要两两进行比较。加了条件筛选,就可以避免笛卡尔积现象了,但是!不会减少记录的匹配次数(=参与查询的表的行数乘积)

对于SQL92,这里看一个简单的例子来方便理解:求员工的名字和所在部门的信息。

a84c6f4a52966776c65cf430bd7d6a4c.gif

在多表查询的时候一般都会将表重命名,这样效率高。

接下来,就看看按连接方式划分的那些连接的格式:

内连接

格式:

    ...

        表1

    [inner] join

        表2

    on

        连接条件

    where

        筛选条件

    ...

以上就是内连接的基本格式了,而等值连接就是条件是等量关系,非等值连接就是条件是非等量关系,自连接就是表1和表2是同一张表,例如:

4a36db6ad22b6dd9c4b1e065aed40a8c.gif

其余的以此类推,这里就不再举例。

外连接

格式:

    ...

        表1

    (left/right) [outer]  join

        表2

    on

        连接条件

    where

        筛选条件

    ...

以上就是外连接的基本格式了,那么什么是左外连接,什么是右外连接呢?我们先看看内连接——它是一种没有主副表之分的连接,凡是表之间能匹配上的记录都是能查出来的。而外连接就有主副表之分了,用外连接就是主要查询主表中的数据,但副表没有数据和主表匹配时,就会生成null与之匹配。因此,和内连接不一样的是,外连接在join前面加了left/right来区分哪一个是主表哪一个是副表,(在以上的两个表中,如果是left,则表1是主表;如果是right,则表2是主表)。

这里为了便于看出外连接和内连接的区别,举一个看似不恰当的例子:求每个员工的补贴是在哪个薪水等级

内连接:

95404ceb108f2f2211e260df9972e0e4.png

外连接:

415b5526f7d901ef19f0a6b43b7a9f6c.png

这是不是就应证了上面那些话,有主表会用null补全。

全连接

全连接就是左右都是主表。在MySQL中没有全连接,但是我们可以用union来实现,等下讲union的时候就明白了。

以上的例子都是两张表进行的,那么如果要进行多张表的话,那该怎么做呢?其实很简单,格式如下:

    ...

        表1

    join

        表2

    on

        连接条件

    join

        表3

    on

        连接条件

    ...

以此类推,用什么查询直接在join前面加就可以了,这里就不再举例。

0c8a867e0c1e9f2b6f1e658bb64fd603.gif子查询语句 0c8a867e0c1e9f2b6f1e658bb64fd603.gif

简单理解就是select语句中继续嵌套select语句,而被嵌套的select语句就称为子查询。

常见的子查询主要位于以下几个位置:

1、select后面

2、from后面

3、where后面

接下来,我们简单看下这三种的简单举例:

求每个部门中的员工个数:

6e198ac71289bc3381bf4ad045773f7c.png

找出每个部门平均工资等级:

d4fe0f9f73ea7630423f2073743a9fcd.png

找出工资大于平均工资的员工:

1c9fd10e8b23261a8c4360c836bd7b1e.png

以上就是简要的子查询的概念,要完成一个子查询就必须先把问题拆解为若干个,然后去拼接。如找出工资大于平均工资的员工,我们就可以先求平均工资(也就是位于where中的子查询),然后再求大于这个平均工资的员工。

0c8a867e0c1e9f2b6f1e658bb64fd603.gif分页查询语句 0c8a867e0c1e9f2b6f1e658bb64fd603.gif

格式为:

select

    ...

[order by]

limit [offset, ] length;

其实就是在之前的DQL语句的结尾中再加一个limit关键字,其中offset表示起始位置,默认为0(第一条记录就为0),而length表示一页中显示几条记录。而且limit只能写在语句的最后!比如:

找出所有员工的第1~5条的记录(第一页):

fdb130358906ca68e118eb505c85fe85.png

找出所有员工的第6~10条的记录(第二页):

079c48f8ceab14cd6574da03cd5dea01.png

找出所有员工的第11~15条的记录(第三页):

49b34018748b970f972bece08935891d.png

从以上我们可以看出这样的一个规律:

如果每页显示的记录数为length,那么,第num页的limit的数值就写(num-1)*length, lengh;

到这,我们又可以更新下执行顺序的问题了:

5、select 

    ..

1、from

    ..

2、where

    ..

3、group by

    ..

4、having

    ..

6、order by

    ..

7、limit

    ..;

0c8a867e0c1e9f2b6f1e658bb64fd603.gif联合查询语句 0c8a867e0c1e9f2b6f1e658bb64fd603.gif

格式为:

查询语句1

union

查询语句2;

用于将查询结果集相加。用union的时候必须要保证列数相同,否则会报错:

7d99be26a6b925b80393f087abb99674.png

而且如果没有要求将表命名的话,结果字段名会显示第一张表的字段名,如:

450f90dc890fadf6a5898d04e455b89f.png

可以看到上面是员工名,下面是部门名,而字段名就是第一张表字段名。

那么怎么用union来实现全连接呢?我们也一样来看一个例子,我们要显示所有部门和所有员工的关系,这时候我们就需要用全连接了(用emp作为主表,可能对应不上部门编号,会被淘汰;用dept作为主表,可能对应不上员工,也会被淘汰):

3894b15a1d3cb22c3e9abfdf6ef9ac44.png

(以上的emp表中多了一个LiHua,其deptno没有对应dept表中的已有的deptno)

可以看到,结果就可以看到所有部门和所有员工的关系了(部门编号为40没有对应员工所以为null,员工名称为LiHua没有对应部门所以也为null)。

ab3d7260cdae8709dc4eaad803fb8c65.png

到这,基本的DQL语句就差不多结束了,从以上我们也知道了SQL语句都是以;结尾的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值