基于SQLServer的SQL语言使用--查询

查询 select

查询也称检索。
必须给出俩条信息:
要选择什么?
选择那一行或那几行;选择那些列或者全部列。
从什么地方选择?
要检索的数据来自那个表。

查询数据库中的表

查询此时所在的数据库中的表(非系统表):

SELECT NAME FROM SYSOBJECTS where type = 'U';

查询数据库中所有表(包含表信息):

SELECT * FROM INFORMATION_SCHEMA.TABLES

查看表的结构

知道了表名,根据表名查看表的结构(包含列名)
查询表结构时,最好单独执行

sp_columns table_1;
sp_help table_1;

知道了表的列名,可以开始查询表中数据了。

开始查询表中数据

查询表中部分列的所有行:
表1中共有四列,此条语句选择三列

select id,age,gender from table_1;

更换检索列的排列,就可以得到排列不同的结果集:

select age,id,gender from table_1;

检索表中所有列的所有行

select * from table_1;

检索语句带星号(*)表示查询所有列
得到表中所有数据
如果表中数据记录非常多时,使用此语句就不太合适了。

限制检索数据的数量

select top 5 * from table_1;

只显示表的前5条数据,但每条数据包含所有列。

包含部分列的限制查询:

select top 3 id,age,phone from table_1;

检索表的前3条数据,包含3个选择列。

只检索不重复的值–distinct

创建一个新的表:
包含三个列(column)

create table 
distinct_table
 (id int not null primary key,
 name varchar(5) not null,
 age int );

为新表插入数据:
因为我们是为了进行去重查询,所以为name,age列填入重复数据

insert into 
distinct_table
 (id,name,age)
values
 (1,'张大',11),
 (2,'张大',22),
 (3,'张三',33),
 (4,'张四',33);

开始去重查询:

select distinct age from table_33;
--得到只包含age列的不重复数据结果集。
select distinct age,name from distinct_table;
--distinct关键字后添加多个列虽然不会报错,但也不会再起到去重作用。
select distinct * from distinct_table;
--执行‘所有列’的去重,效果与不执行去重相同。
select * from distinct_table;

过滤数据检索–where

为检索数据添加条件,指定范围
检索条件在表名之后给出(from表名 where条件)

select * from distinct_table 
where age = 11;
--添加过滤条件,年龄等于11
--检索年龄等于11的记录
select * from distinct_table
where name = '张大';
--where子句中用''单引号来限定字符串。
select * from distinct_table 
where age <= 22;
--检索表中,年龄小于等于22的记录,包括22。
select * from distinct_table
where age >=22;
--检索年龄大于等于22的记录,包括22.
select * from distinct_table
where age < 33;
--检索年龄小于33的记录。
select * from distinct_table
where age > 22;
--检索年龄大于22的记录。
select * from distinct_table
where age != 33;
--检索年龄不等于33的记录。
select * from distinct_table
where age <> 33;
select * from distinct_table
where age !< 33;
--检索年龄不小于33的记录,不包括33.
select * from distinct_table
where age !> 33;
--检索年龄不大于33的记录,因为没有年龄大于33记录所有全部检索。

空值检索–is null

select * from table_2
where nowdate is null;
--检索现在时间列是空的记录。

非空值检索

select * from table_2
where nowdate is not null;
--检索现在时间列不为空的记录。

高级过滤–and–or

and ‘与’ 操作符,俩个或多个条件同时满足时,返回记录。
or ‘或’ 操作符,有一个条件满足时就返回数据。
WHERE语句可以包含任意数量的AND和OR操作符。
同时使用时and的优先级高于or
圆括号有着比and和or更高的优先级。

select * from distinct_table
where id =2 and name = '张大';
--检索id等于2与名称是张大的记录。
--俩个或多个条件同时满足时,返回记录。
select * from distinct_table
where id =2 or age = 77;
select * from distinct_table
where   age = 77  or id =2;
/*
俩条检索的结果相同
检索id等于2或者年龄等于77的记录。
年龄列中没有77的值,所以只返回id等于2的记录。
*/
select * from distinct_table
where id =2 or age = 33;
--俩个条件都满足时,则俩个条件的结果都返回。

范围值检索–between

在俩者之间

select * from distinct_table
where age between 11 and 22;
--检索年龄在11与22之间的记录。and‘与’操作符

IN操作符

用来指定条件范围,范围中的每个条件都可以进行匹配,即使有不匹配 的选项也不会报错

select * from distinct_table
where   name  in ('张四', '张三') ;
--在有很多合法选项时,IN操作符的语法更加清楚,更加直观
select * from distinct_table
where   name  in ('张四', '张三','王五') ;
--表名称列中王五值不存在,但不会报错。
--IN操作符一般比一组OR操作符执行更快
select * from distinct_table
where age in (select age from distinct_table
where age = 33);
--它的功能与OR相当。
--IN的最大优点是可以包含其他SELECT语句,能更动态的建立WHERE子句

NOT操作符

WHERE子句中用来否定其后面条件的关键字
NOT从不单独使用(它总是与其他操作符一起使用)NOT关键字可以用来在要过滤的列前

select * from distinct_table
where not age in (select age from distinct_table
where age = 33);
--检索年龄不包含33的记录
select * from distinct_table
where not name in ('张大');
--检索名称列不为张大的记录
--WHERE子句  NOT关键字 列名 IN关键字(?)

模糊比配–like

关键字like,用来匹配值的一部分
通配符的搜索只能用于文本字段(字符串),非文本数据类型不能使用通配符搜索
不要过多的使用通配符,如果其他操作符能达到相同的目的,应该使用其他操作符
尽量不要将他们放在搜索模式的开始处,这样的检索速度最慢

百分号(%)通配符

--%表示任意字符出现任意次数
select * from distinct_table
where name like '张%';
--检索名称中姓张的记录。

除了可以匹配一个到多个字符之外,还可以匹配0个字符

select * from distinct_table
where name like '张%大';
--检索名称列以张开头以三结尾,的记录。
--通配符无法匹配NULL
--注意通配符匹配时,值后是否为空格
--此表中的名称列数据类型为变长字符串,如果是定长字符串,则空余字节会用NULL填充
select * from distinct_table
where name like '张%大%';
--如果值后用空格填充,则增加一个通配符进行匹配。

下划线(_)通配符
匹配一个任意字符

select * from distinct_table
where name like '_大';
--匹配名称列中,一个任意字符一个为大的名称。

方括号([ ])通配符

select * from distinct_table
where age like '[12]%';
--检索年龄列中以1或2开头的任意数字。
select * from distinct_table
where age like '[12]%[2]';
--检索年龄列中以1或2开头的,以2结尾的任意数字。

检索数据排序–order by

将检索的数据按需要的列进行排序。
关键字DESC降序(从大到小),ASC升序(从小到大)为默认

select * from distinct_table
order  by  age desc;
--将检索的数据以年龄从大到小排列
select * from distinct_table
order  by  age asc;
--将检索的数据以年龄从小到大排序。
select * from distinct_table
order  by  age;
--将检索的数据以年龄从小到大排序,未使用关键字ASC,ASC为默认。

在指定一条ORDER
BY子句时,应该保证它是SELECT语句中的最后一条子句。否则会出现错误!

select * from distinct_table
where age < 33 order by age desc;

《按多个列进行排序》
按多个列排序时,简单的指定列名,列名之间用逗号隔开即可

select * from table_1
order by id,age desc;
--先按ID列进行排序,再按AGE列进行排序,排序为降序(从大到小)

《按检索列位置进行排序》
使用select语句中的检索列位置进行排序

select id,age,gender,phone from table_1
order by 1,2 desc;
--先以ID列进行排序,再以age列进行排序,排序方式为降序。

创建计算字段

直接从数据库中,检索出转换,计算或格式化后的数据。
计算字段是在SELECT运行时创建的

拼接:将值连接到一起组成单个值

select name + site from table_2;
--将name列与site列连接到一起组成一个值。
select name +'('+site+')' from table_2;
--在连接的新值中添加()用于区分。

拼接时,字符串型和INT型不能混合。

select name +'('+id+')' from table_2;
--在将 varchar 值 ')' 转换成数据类型 int 时失败。

别名–AS

别名用关键字 AS赋予
别名也被称作导出列

拼接后的字段只是一个值没有名称,未命名的列不能用于客户端应用

select name +'('+site+') ' as ns2 from table_2;
--为检索出的数据集合添加别名,别名为ns2。

为表赋予别名

在这里插入代码片

去掉空格

当检索列为定长字符型时,如何去掉空格。
此表中存在定长字符串类型

关键字RTRIM()去掉列末尾空格

select name + '('+rtrim(gender)+')' from table_1;
--将gender列左侧的空格去掉
--将name列与gender列的值拼接为一个值,gender列末尾的空格去掉
select rtrim(name) + '('+gender+')' from table_1;
--去掉name列的空格,并将name与gender列的值拼接。

关键字LTRIM()去掉列开头空格

select name + '('+ltrim(string_1)+')' from table_1;
--去掉string_1列开头位置的空格,并与name列拼接

算数计算

SQL算术计算符

--加  +
--减  - 
--乘  *
--除  /
--SELCET语句忽略FROM子句之后,就是一个简单的访问和处理表达式
select 3 + 4 as addition;
--加法,addition
select 9999999 - 123456 as subtraction;
--减法,subtraction
select 78 * 88 as multiplication;
--乘法,multiplication
select 87879 / 2343 as division;
--除法,division

函数

如果你决定使用函数,应该保证做好代码注释,方便以后你和其他人方便知道所编写的代码的含义

用于处理文本字符串的,《文本函数》
用于在数值数据上进行算数操作的,《数值函数》
用于处理日期和时间值并从中提取特定成分的,《日期和时间函数》
返回DBMS正在使用的特殊信息的,《系统函数》

UPPER()函数,将文本转换为大写

select 
id,
name,
age,
gender,
phone,
upper(string_1),
order_date,
number_1 
from table_1;
--upper()关键字,将string_1列的字符串转换为大写。

lower()函数,将文本转换为小写

id,
name,
age,
gender,
phone,
lower(string_1),
order_date,
number_1 
from table_1;
--lower()将string_1列中的字符串转变为小写

left()返回字符串左侧的字符

select left('fhhjkiunk',3);
select left(string_1,6) from table_1;
--返回字符串左侧的字符,返回字符串左侧几个字符,包括空格。

RIGHT()返回字符串右边的字符

select right(string_1,6) from table_1;
--返回字符串右侧的指定字符,包括空格。

len()返回字符串的长度,不包括空格

select len(string_1) from table_1 order by id;
--返回string_1列所有行字符串的长度,并按id列排序。
select len(string_1) from table_1
where id = 3;
--返回指定行string_1列字符串的长度

ltrim()去掉字符串左边空格

select ltrim(string_1) from table_1;
--ltrim()去掉字符串左侧的空格。

rtrim()去掉字符串右边空格

select rtrim(string_1) from table_1;
--rtrim()去掉字符串右侧的空格。
select len(rtrim(string_1)) from table_1 order by id;
--返回去掉string_1列右侧的空格后的字符串数量并按照ID列排序。

SOUNDEX()返回字符串的SOUNDEX值(即发音比较)

《时间和日期处理函数》

时间单位

year(yy)            年份
quarter(qq)         季度
month(mm)           月份
day(dd)             日
week(wk)hour(hh)minute(mi)second(ss)        秒
millisecond(ms)   毫秒

返回系统当前日期时间–getdate()

select getdate();
--返回系统当前的日期时间

增加并返回日期–dateadd()

 select dateadd(year,33,'2020-7-17');
 --为日期增加年数并返回结果。
 select dateadd(yy,4,(select getdate()));
 --为当前日期时间增加4年。
 select dateadd(qq,4,(select getdate()));
 --为当前日期时间增加4个季度。
 select dateadd(mm,4,(select getdate()));
 --为当前日期增加4个月。
  select dateadd(dd,4,(select getdate()));
--当前日期增加4天。
select dateadd(wk,4,(select getdate()));
--当前日期增加4周。
select dateadd(hh,4,(select getdate()));
--当前日期增加4小时。
select dateadd(mi,4,(select getdate()));
--当前日期增加4分钟。
select dateadd(ss,40,(select getdate()));
--当前日期增加40秒
select dateadd(ms,40,(select getdate()));
--当前日期增加40毫秒。

datediff 返回俩个指定日期的边界数/差

select datediff(day,'2002-05-23','2200-03-03') ;
--检索俩个日期的相差天数,72237天。
select datediff(day,'2200-03-03','2002-05-23') ;
--检索俩个日期相差的天数,-72237天。

datepart 返回代表指定日期的指定日期部分的整数

select DATEPART(year, '2024-07-11');
--返回指定日期的年份,。
select datepart(month, '2024-07-11');
--返回指定日期的月份。

datename 返回代表指定日期的指定日期部分的字符串

select datename(weekday, '2030-07-09');
--返回指定日期为星期几,星期二。
select datename(quarter, '2020-07-17');
--返回当前日期的季度。

数值函数

数值处理函数

select cos(66) as '返回一个角度的余玄';
--cos()返回一个角度的余玄。
select PI() as '返回圆周率';
--pi()返回圆周率。
select abs(66/33) AS '返回一个数的绝对值';
--abs()返回一个数的绝对值。
select EXP(78) AS '返回一个数的指数值';
--exp()返回一个数的指数值。
select SIN(90) AS '返回一个角度的正玄';
--sin()返回一个角度的正玄。
select SQRT(7) AS '返回一个数的平方根';
--sqrt()返回一个数的平方根.
select TAN(89) AS '返回一个角度的正切';
--tan()返回一个角度的正切.

汇总数据/聚集函数

count()返回某列的行数

select count(number_1) AS '返回行数' from table_1;
--count(),返回此列的行数。

AVG()返回某列的平均值

select AVG(age) from table_1;
--avg(),返回年龄列的平均值。

MAX() 返回某列的最大值

select MAX(age) as '返回某列的最大值'from table_1;
--max(),返回某列的最大值

MIN() 返回某列的最小值

select MIN(age) as '返回某列的最小值' from table_1;
--min(),返回某列的最小值

SUM() 返回某列值之和

select SUM(age) as '返回某列值之和' from table_1;
--sum(),返回某列值之和

返回列不同值的和

select SUM(distinct(age)) as '返回不同值的和' from table_1;
--关键字,sum(),distinct()

组合聚集函数

select 
 count(id),
 max(age),
 min(phone),
 avg(number_1),
 sum(number_1)
from table_1;
--不同列使用不同的聚集函数。
select 
 count(age),
 max(age),
 min(age),
 avg(age),
 sum(age)
from table_1;
--相同列使用不同的聚集函数。

分组数据–GROUP BY

分组数据是通过GROUP BY
分组过滤数据是通过HAVING

如果在SELECT中使用表达式,则必须在GROUP BY子句中指定相同的表达式。不能使用别名

select name,count(*) from table_1 group by name;
--统计相同名称的数量,并以名称分组。

除聚集计算语句外,SELECT语句中的每一列都必须在GROUP BY中给出

select name,age,count(*) from table_1 group by name;
--age未曾在检索中列出,故报错。
/*
HAVING 子句中的列 'table_1.age' 无效,
因为该列没有包含在聚合函数或 GROUP BY 子句中。
*/

GROUP BY子句列未出现在检索列时,不报错

select name,count(*) from table_1 group by name,age;

GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前

过滤分组

select name,age from table_1 GROUP BY name HAVING age > 12;
--将age大于12的检索列按name列进行分组。

GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前

select 
 name,
 age 
from table_1
where
 id < 8
 GROUP BY 
 name,
 age 
HAVING 
 age > 12 
ORDER BY 
 age;
 /*
select name,age from table_1
where id < 8
GROUP BY name,age 
HAVING age > 12 
ORDER BY age;
*/

不可以使用,GROUP BY未给出的列进行ORDER BY排序

SELECT子句及其顺序

SELECT子句及其顺序
Select    要返回的列或表达式   
From   从中检索数据的表
Where  行级过滤
Group by 分组说明
Having  组级过滤
Order by  输出排序顺序

子查询

即嵌套在其他查询中的查询。

select * from table_1 where age in
 (select age from table_1 where age <= 12);
--将内查询的结果作为外查询的条件。
select * from table_1 
where id in
(select id from table_2 where  table_2.nowdate is not null );
--表1和表2通过外键连接。
--子查询可以用不同表的结果为条件

对于嵌套的子查询的数目没有限制,但是实际操作中由于性能的限制,不能嵌套太多的子查询

联结表

指定要联结的所有表,以及关联它们的方式即可。
要保证所有的联结都有WHERE子句,否则会返回比想要的多得多的数据

不使用WHERE子句会造成笛卡二积又被称为叉联结

select age,gender,name,site from
table_1,table_2;
--为使用where子句,造成笛卡尔积。又叫叉联结。

内联结–inner join where格式

select 
 table_1.id,table_1.age,table_1.gender,table_1.phone,
 table_2.name,table_2.site,table_2.nowdate,table_2.id
from table_1,table_2
where table_1.id = table_2.id;
--没有使用 inner join 的等值联结

内联结 INNER JOIN 标准格式


select 
 table_1.id,table_1.age,table_1.gender,table_1.phone,
 table_2.name,table_2.site,table_2.nowdate,table_2.id
from table_1 inner join table_2
on table_1.id = table_2.id;
--标准格式的内联结 inner join ...用on代替where。

为联结添加过滤,检索指定行。

select 
 table_1.id,table_1.age,table_1.gender,table_1.phone,
 table_2.name,table_2.site,table_2.nowdate,table_2.id
from table_1 inner join table_2
on table_1.id = table_2.id
and table_1.id = 3;
--为联结添加过滤,检索指定行。只检索id为3的行。

SQL不限制一条SELECT语句可以联结的表的数目,联结的表越多,性能下降的越厉害。
使用联结的同时增加过滤

select 
 table_1.id,table_1.age,table_1.gender,table_1.phone,
 table_2.name,table_2.site,table_2.nowdate,table_2.id
from table_1,table_2
where table_1.id = table_2.id
and table_1.id in(1,2,3);
--等值联结,联结并过滤数据。

表别名
SQL使用表别名。
缩短SQL语句;
允许在一条SELECT语句中多次使用相同的表。

缩短SQL语句;

select 
 t1.id,t1.age,t1.gender,t1.phone,
 t2.name,t2.site,t2.nowdate,t2.id
from table_1 as t1,table_2 as t2
where t1.id = t2.id
and t1.id in(1,2,3);
--给table_1,table_2赋予别名t1,t2.

在查询中使用表别名可以缩短SQL语句,但是表别名只在查询中使用,表别名不会返回到客户端。

允许在一条SELECT语句中多次使用相同的表
自联结
自联结作为外部语句,用来替代从相同表中检索数据的子查询语句
虽然结果相同,但许多DBMS处理联结比子查询快得多。

select t1.name,t1.site,t1.nowdate,t1.id
from table_2 as t1 , table_2 as t3
where t1.id = t3.id
and t1.name in ('老大','老二','老三');
--将table_2表赋予别名t1,t3在同一个查询中引用俩次。
--当一个表在一条查询中出现俩次时,需要为他赋予别名。否则会报错!

自然联结
自然联结排除多次出现,使每一列只返回一次。
通配符(SELECT
*)只对第一个表使用。所有其他列明确列出,所以没有重复的列被检索出来

select * ,age,gender,phone from table_1 inner join table_2
on table_1.id = table_2.id;
--俩个表,一个用*表示全部使用,一个明确列出。

外联结–OUTER JOIN
包含哪些在相关表中没有关联的行。称为外联结
外联结关键字,left左,right右
在使用OUTER JOIN语法时,必须使用RIGHT(右)或LEFT(左)关键字指定包括其所有行的表

左外联结–LEFT OUTER JOIN

select table_1.id,table_1.age,table_1.gender,table_1.phone,
 distinct_table.name,distinct_table.age,distinct_table.id
from table_1 left outer join distinct_table
on table_1.id = distinct_table.id ;

--左外联结,返回左侧表所有行,右侧表过滤行

右外联结–RIGHT OUTER JOIN

select table_1.id,table_1.age,table_1.gender,table_1.phone,
 distinct_table.name,distinct_table.age,distinct_table.id
from table_1 right outer join distinct_table
on table_1.id = distinct_table.id ;
--右外联结,返回右侧表所有行,左侧表过滤行。

左外联结与右外联结唯一的差别是所关联的表的顺序,调整表顺序,左外联结可以转变为右外联结。
全外联结–FULL OUTER JOIN
包含所有关联的行与不关联的行,注意:是关联行与不关联行,不是列。

select table_1.id,table_1.age,table_1.gender,table_1.phone,
 distinct_table.name,distinct_table.age,distinct_table.id
from table_1 full outer join distinct_table
on table_1.id = distinct_table.id ;
--全外联结,返回俩个表中的所有行。

使用带聚集函数的联结

select max(table_1.id) as id,
  count(distinct_table.age) as age
from table_1 inner join distinct_table
on table_1.id = distinct_table.id;
--

组合查询–UNION并集

SQL允许执行多个查询,并将结果作为一个查询结果集返回。这些组合查询称为并(union)或者复合查询(compound query)–带有自动去重的效果

使用组合查询的情况:
在一个查询中从不同的表返回结构数据;
对一个表执行多个查询,按一个查询返回数据。
(多数情况下,组合相同表的俩个查询所完成的工作与具有多个WHERE子句条件的一个查询所完成的工作相同。
任何具有多个WHERE子句的SELECT语句都可以作为一个组合查询。)

将同一个表中的俩次查询,返回到一个结果集。

select
name,age from table_1
union
select
gender,phone from table_1 ;
--将同一个表中的俩次查询,返回到一个结果集

将不同表的查询返回到一个结果集



select
name,age from table_1
union
select
name,age from join_1;
--将不同表的查询返回到一个结果集

组合查询规则

  1. UNION必须由俩条或俩条以上的SELECT语句组成,语句之间用关键字UNION分隔。
  2. UNION中的每个查询必须包含相同的列,表达式或聚集函数(列次序可以不同)。
  3. 列数据类型必须兼容。

UNION 从查询结果集中自动去除重复的行
如果想返回所有的匹配行,可使用UNION ALL

select
name,age from table_1
union all
select
name,age from join_1;
--返回所有匹配行。

对结果集进行排序



select
name,age from table_1
union all
select
name,age from join_1
     order by age;
/*
在用UNION组合查询时,只能使用一条ORDER BY子句,
他必须位于最后一条SELECT语句之后。
*/
/*
某些DBMS还支持另外的俩种UNION:
EXCEPT/MINUS,可以用来检索旨在第一个表中存在而在第二个表中不存在的行;

INTERSECT
可以用来检索俩个表中都存在的行。
*/

你可能感兴趣的:(sql,数据库)