数据库复习:1
数据库复习:1
基础概念
SQL主要分成四部分:
(1)数据定义。(DDL)用于定义SQL模式、基本表、视图和索引的创建和撤消操作。
(2)数据操纵。(DML)数据操纵分成数据查询和数据更新两类。数据更新又分成插入、删除、和修改三种操作。
(3)数据控制。(DCL)包括对基本表和视图的授权,完整性规则的描述,事务控制等内容。
(4)嵌入式SQL的使用规定。(TCL)涉及到SQL语句嵌入在宿主语言程序中使用的规则。
sql指令回忆
-
group by:GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组。
我们拥有下面这个 "Orders" 表:
O_Id OrderDate OrderPrice Customer 1 2008/12/29 1000 Bush 2 2008/11/23 1600 Carter 3 2008/10/05 700 Bush 4 2008/09/28 300 Bush 5 2008/08/06 2000 Adams 6 2008/07/21 100 Carter 现在,我们希望查找每个客户的总金额(总订单)。
我们想要使用 GROUP BY 语句对客户进行组合。
我们使用下列 SQL 语句:
SELECT Customer,SUM(OrderPrice) FROM Orders GROUP BY Customer结果集类似这样:
Customer SUM(OrderPrice) Bush 2000 Carter 1700 Adams 2000 -
having:对查询及统计结果再做一次筛选。注意,having通常和group by一起用,但是不是必须和它一起,只要有select就可以用
我们拥有下面这个 "Orders" 表:
O_Id OrderDate OrderPrice Customer 1 2008/12/29 1000 Bush 2 2008/11/23 1600 Carter 3 2008/10/05 700 Bush 4 2008/09/28 300 Bush 5 2008/08/06 2000 Adams 6 2008/07/21 100 Carter 现在,我们希望查找订单总金额少于 2000 的客户。
我们使用如下 SQL 语句:
SELECT Customer,SUM(OrderPrice) FROM Orders GROUP BY Customer HAVING SUM(OrderPrice)<2000结果集类似:
Customer SUM(OrderPrice) Carter 1700 -
order by:用于根据指定的列对结果集进行排序。
原始的表 (用在例子中的):
Orders 表:
Company OrderNumber IBM 3532 W3School 2356 Apple 4698 W3School 6953 实例 1
以字母顺序显示公司名称:
SELECT Company, OrderNumber FROM Orders ORDER BY Company结果:
Company OrderNumber Apple 4698 IBM 3532 W3School 6953 W3School 2356 -
truncate和drop指令的区别:
DROP TABLE会清除整个table,而TRUNCATE TABLE只是清楚表中的所有数据
-
储存过程
存储过程 Procedure 是一组为了完成特定功能的 SQL 语句集合,经编译后存储在数据库中,用户通过指定存储过程的名称并给出参数来执行。
下述代码创建了一个被称为 “LatestTasks” 的存储过程。
它接受一个参数名为 @Count. 当调用这个存储过程,通过 @count 参数,它决定你想要多少行返回。
代码如下:
CREATE PROCEDURE LatestTasks @Count int AS SET ROWCOUNT @Count SELECT TaskName AS LatestTasks, DateCreated FROM Tasks ORDER BY DateCreated DESC -
count: COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入)
注意这里是列的数目,有值重复的列是没关系的,依然计数
可以看一下这道题:
表结构如下:
CREATE TABLE `score` ( `id` int(11) NOT NULL AUTO_INCREMENT, `sno` int(11) NOT NULL, `cno` tinyint(4) NOT NULL, `score` tinyint(4) DEFAULT NULL, PRIMARY KEY (`id`) ) ;以下查询语句结果一定相等的是()
A.SELECT sum(score) / count(*) FROM score WHERE cno = 2;
B.SELECT sum(score) / count(id) FROM score WHERE cno = 2;
C.SELECT sum(score) / count(sno) FROM score WHERE cno = 2;
D.SELECT sum(score) / count(score) FROM score WHERE cno = 2;
E.SELECT sum(score) / count(1) FROM score WHERE cno = 2;
F.SELECT avg(score) FROM score WHERE cno = 2;
正确答案是:A,B,C,E/D,F
注意这里的count(1):count(1),其实就是计算一共有多少符合条件的行。1并不是表示第一个字段,而是表示一个固定值。
而A,B,C,E中各个count的列(或者1)都有一个特点,就是不会置null,所以count出来的结果一样。而score是没有设置NOT NULL的,所以算出来的结果可能和ABCE不一样,但是它和F一样
例题
select语句完整语法:
select 目标表的列名或列表达式序列
from 基本表名和(或)视图序列
[where 行条件表达式]
[group by 列名序列]
[having 组条件表达式]
- [order by 列名[asc | desc]],则sql语句的执行顺序是
正确答案是:2),3),4),1) ,5):先看是哪个表,然后使用where的条件筛选,之后对筛选后的结果使用group by分组,再用having筛选。再使用select选出要显示的列,然后order by决定排序
-
请取出 BORROW表中日期(RDATE字段)为当天的所有记录?(RDATE字段为datetime型,包含日期与时间)。SQL语句实现正确的是:( )
错误答案是:select * from BORROW where RDATE=getdate()
正确答案是:select * from BORROW where datediff(dd,RDATE,getdate())=0
这是为什么呢,因为getdate()得到的结果是date类型的,而题中说了RDATE是datetime类型,还有个time,所以不能直接比
DATEDIFF() 函数返回两个日期之间的时间。
语法
DATEDIFF(datepart,startdate,enddate)datediff(dd,RDDATE,getdate())==0,就是要求一个以日为单位(dd),和当前日期(getdate)相差为0日的RDDATE
-
一个复杂的sql:
有一个名为app的MySQL数据库表,其建表语句如下:
create table `app`(`app_id` int(10) default 0,`version_code` int(10) default 0,`download_count` int(10) default 0)engine=InnoDB default charset=utf8mb4;当前表中数据记录如下,一条记录表示某个应用的某个版本的下载量记录:
+--------+--------------+----------------+
| app_id | version_code | download_count |
+--------+--------------+----------------+
| 1 | 10 | 90 |
| 1 | 11 | 100 |
| 1 | 10 | 20 |
| 2 | 15 | 10 |
| 2 | 16 | 15 |
| 2 | 17 | 30 |
| 2 | 16 | 5 |
| 3 | 2 | 50 |
+--------+--------------+----------------+sql语句如下,想自己试的同学可以复制试一下:
insert into `app` values(1,10,90); insert into `app` values(1,11,100); insert into `app` values(1,10,20); insert into `app` values(2,15,10); insert into `app` values(2,16,15); insert into `app` values(2,17,30); insert into `app` values(2,16,5); insert into `app` values(3,2,50);问: 下面那个MySQL语句可以查出每个应用中总下载量最大的版本号和次数( )?
下面的方法被证明是不可行的:
正确答案:
select t.app_id, t.version_code, max(t.download_sum) from (select app_id, version_code, sum(download_count) download_sum from app group by app_id, version_code order by download_sum desc) as t group by t.app_id;解析:先对原始数据加和(有版本号和app_id重复的项,要加在一起),然后以app_id分类,再加一个条件是在每类中选max(download_sum),留下的tuple自然是每个应用中总下载量最大的版本号和次数
https://blog.csdn.net/l1028386804/article/details/54657412
这样的语句是非SQL标准的,虽然能够在MySQL数据库中执行成功,但返回的却是未知的
(如果sql_mode开启了only_full_group_by,则不会执行成功。)
可能ip字段会取uid分组前的第一个row的值,显然不是所需信息
原文中处理这个问题的方法也是再写一个子查询,这里也可以这样做,虽然会让语句非常复杂:
select t.app_id,t.version_code,t.download_sum from (select app_id,version_code,sum(download_count) download_sum from app group by app_id,version_code order by download_sum desc) as t where (t.app_id,t.download_sum)in ( select t.app_id,max(t.download_sum) max from(select app_id,version_code,sum(download_count) download_sum from app group by app_id,version_code order by download_sum desc) as t group by t.app_id ) order by t.app_id;
btw,这里正好验证一下根据多个表项进行group by的效果:
select app_id,version_code,sum(download_count) download_sum from app group by app_id,version_code order by download_sum desc;
执行结果是:
+--------+--------------+--------------+
| app_id | version_code | download_sum |
+--------+--------------+--------------+
| 1 | 10 | 110 |
| 1 | 11 | 100 |
| 3 | 2 | 50 |
| 2 | 17 | 30 |
| 2 | 16 | 20 |
| 2 | 15 | 10 |
+--------+--------------+--------------+
由此可见,各个表项是等价的,就是每个特殊情况就展开一次

浙公网安备 33010602011771号