当前位置:首页 » 编程语言 » SQL解惑笔记
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

SQL解惑笔记

发布时间: 2023-08-17 12:02:20

1. oracle笔记-动态sql

第 章 动态SQL

为何使用动态SQL

实现动态SQL有两种方式 DBMS_SQL和本地动态SQL(EXECUTE IMMEIDATE)

主要从以下方面考虑使用哪种方式

是否知道涉及的列数和类型

DBMS_SQL包括了一个可以 描述 结果集的存储过程(DBMS_SQL DESCRIBE_COLUMNS) 而本地动态SQL没有

是否知道可能涉及的绑定变量数和类型

DBMS_SQL允许过程化的绑定语句的输入 而本地动态SQL需要在编译时确定

是否使用 数组化 操作(Array Processing)

DBMS_SQL允许 而本地动态SQL基本不可以 但可以用其他方式实现(对查询可用FETCH BULK COLLECT INTO 对INSERT等 可用一个BEGIN … END块中加循环实现)

是否在同一个会话中多次执行同一语句

DBMS_SQL可以分析一次执行多次 而本地动态SQL会在每次执行时进行软分析

是否需要用REF CURSOR返回结果集

仅本地动态SQL可用REF CURSOR返回结果集

如何使用动态SQL

DBMS_SQL

调用OPEN_CURSOR获得一个游标句柄

调用PARSE分析语句 一个游标句柄可以用于多条不同的已分析语句 但一个时间点仅一条有效

调用BIND_VARIABLE或BIND_ARRAY来提供语句的任何输入

若是一个查询(SELECT语句) 调用DIFINE_COLUMN或DEFINE_ARRAY来告知Oracle如何返回结果

调用EXECUTE执行语句

若是一个查询 调用FETCH_ROWS来读取数据 可以使用COLUMN_VALUE从SELECT列表根据位置获得这些值

否则 若是一个PL/SQL块或带有RETURN子句的DML语句 可以调用VARIABLE_VALUE从块中根据变量名获得OUT值

调用CLOSE_CURSOR

注意这里对任何异常都应该处理 以关闭游标 防止泄露资源

本地动态SQL

EXECUTE IMMEDIATE 语句

[INTO {变量 变量 … 变量N | 记录体}]

[USING [IN | OUT | IN OUT] 绑定变量 … 绑定变量N]

[{RETURNING | RETURN} INTO 输出 [ … 输出N]…]

注意本地动态SQL仅支持弱类型REF CURSOR 即对于REF CURSOR 不支持BULK COLLECT

最后说明

lishixin/Article/program/Oracle/201311/18948

2. SQL计算电商各项指标数据

本次笔记主要是记录通过SQL计算电商各项指标数据,包括AARRR部分指标、RFM模型等常用的指标数据;

平台指标:

商品指标:

用户行为指标:

RFM模型:见之前的文章《 SQL建立RFM模型指标的两种方法对比 》

用户留存率:见之前文章《 SQL 查询用户留存率(根据两种不同定义计算) 》

首先我们导入相关数据,并去重数据放进新表 temp_trade;

由于时间关系,以导入如下数据,期间利用
SET date_time = STR_TO_DATE(time,'%Y-%m-%d %H');
set dates=date(date_time);
这两个函数对原表(红框)日期进行处理;

再检查一下关键字段有无缺失值

查询后得出并无缺失。

查询结果无异常值;

检查用户行为数据有没有其他类型;

查询结果无异常值;

-- 建新表,放进 去重后的 数据

create table temp_trade like o_retailers_trade_user;
insert into temp_trade select distinct * from o_retailers_trade_user;

查询结果:

这里定义跳失率=只有浏览行为的用户数/总用户数

查询结果

这里的购买转化率定义为:某段时间产生购买行为的用户数/所有到达店铺的访客人数

查询结果:

同时可以通过这算法求得:每天总行为次数、每天点击次数、收藏次数、加购物⻋次数、购买次数

查询结果如下:

由于转化率的对象是商品,所以以商品id做分组,求对应的用户行为数求和。可得出每商品的在该段时间内的浏览、收藏、加购、购买次数,同时可求得商品购买转化率。

查询结果:

此方法与上面商品转化率大致相同,分组对象改为品类id即可。

查询结果:

首先创建hours的新字段,并提取时间;

查询结果如下:

首先求出各用户的购买次数

查询结果:

用case when函数统计出各复购买次数的用户数

查询结果如下:

最后将行为串联起来,并对其进行用户数统计;

查询结果如下:

(完结)

3. SQL中left join on 、right join on、inner join on之间的区别

最近在入门SQL,记录下自己学习的一些笔记。

left join(左联接) 返回包括以左表主表,左表中的所有记录和右表中联结字段相等(左表中匹配不到的字段对应的值为null)即:左表的记录将会全部表示出来,而右表只会显示符合搜索条件的记录。

right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录

       inner join(等值连接) 只返回两个表中联结字段相等的行,即通过相应条件交集后展示的所有字段的大表

举例如下: 

--------------------------------------------

表A记录如下:

aIDaNum

1a20050111

2a20050112

3a20050113

4a20050114

5a20050115

表槐散B记录如下:

bIDbName

12006032401

22006032402

32006032403

42006032404

82006032408

--------------------------------------------

1.left join

sql语句如下: 

select * from A

left join B 

on A.aID = B.bID

结果如下:

aIDaNumbIDbName

1a2005011112006032401

2a2005011222006032402

3a2005011332006032403

4a2005011442006032404

5a20050115NULLNULL

(所影响的行数为 5 行)

结果说明:

left join是以A表的记录为基础的,A可以看成左表,B可以看成右表,left join是以左表为准的.

换句话说,左表(A)的记录将会瞎明物全部表示出来,而右表(B)只会显示符合搜索条件的记录(例子中为: A.aID = B.bID).B表记录不足的地方均为NULL.

--------------------------------------------

2.right join

sql语句如下: 

select * from A

right join B 

on A.aID = B.bID

结果如下:

aIDaNum磨液bIDbName

1a2005011112006032401

2a2005011222006032402

3a2005011332006032403

4a2005011442006032404

NULLNULL  82006032408

(所影响的行数为 5 行)

结果说明:

仔细观察一下,就会发现,和left join的结果刚好相反,这次是以右表(B)为基础的,A表不足的地方用NULL填充.

--------------------------------------------

3.inner join

sql语句如下: 

select * from A

innerjoin B 

on A.aID = B.bID

结果如下:

aIDaNumbIDbName

1a2005011112006032401

2a2005011222006032402

3a2005011332006032403

4a2005011442006032404

结果说明:

很明显,这里只显示出了 A.aID = B.bID的记录.这说明inner join并不以谁为基础,它只显示符合条件的记录.

从SQL开始入门,其他的语言继续学习。生命不停,学习不止!

4. 数据分析课程笔记 - 19 - HiveSQL 常用优化技巧

大家好呀,这节课学习 HiveSQL 的常用优化技巧。由于 Hive 主要用来处理非常大的数据,运行过程由于通常要经过 MapRece 的过程,因此不像 MySQL 一样很快出结果。而使用不同方法写出来的 HiveSQL 语句执行效率也是不一样的,因此为了减少等待的时间,提高服务器的运行效率,我们需要在 HiveSQL 的语句上进行一些优化。

本节课的主要内容

引言
1、技巧一:列裁剪和分区裁剪
(1)列裁剪
(2)分区裁剪
2、技巧二:排序技巧——sort by代替order by
3、技巧三:去重技巧——用group by来替换distinct
4、技巧四:聚合技巧——grouping sets、cube、rollup
(1)grouping sets
(2)cube
(3)rollup
5、技巧五:换个思路解题
6、技巧六:union all时可以开启并发执行
7、技巧七:表连接优化
8、技巧八:遵循严格模式

Hive 作为大数据领域常用的数据仓库组件,在平时设计和查询时要特别注意效率。影响Hive效率的几乎从不是数据量过大,而是数据倾斜、数据冗余、job 或 I/O 过多、MapRece 分配不合理等等。对 Hive 的调优既包含对HiveSQL 语句本身的优化,也包含 Hive 配置项和 MR 方面的调整。

列裁剪就是在查询时只读取需要的列。当列很多或者数据量很大时,如果select 所有的列或者不指定分区,导致的全表扫描和全分区扫描效率都很低。Hive中与列裁剪优化相关的配置项是 hive.optimize.cp ,默认是 true 。

分区裁剪就是在查询时只读需要的分区。Hive中与分区裁剪优化相关的则是 hive.optimize.pruner ,默认是 true 。

HiveSQL中的 order by 与其他 SQL 语言中的功能一样,就是将结果按某个字段全局排序,这会导致所有map端数据都进入一个 rece 中,在数据量大时可能会长时间计算不完。

如果使用 sort by ,那么就会视情况启动多个 recer 进行排序,并且保证每个 recer 内局部有序。为了控制 map 端数据分配到 rece 的 key,往往还要配合 distribute by 一同使用。如果不加 distribute by 的话,map 端数据就会随机分配给 recer。

这里需要解释一下, distribute by 和 sort by 结合使用是如何相较于 order by 提升运行效率的。

假如我们要对一张很大的用户信息表按照年龄进行分组,优化前的写法是直接 order by age 。使用 distribute by 和 sort by 结合进行优化的时候, sort by 后面还是 age 这个排序字段, distribute by 后面选择一个没有重复值的均匀字段,比如 user_id 。

这样做的原因是,通常用户的年龄分布是不均匀的,比如20岁以下和50岁以上的人非常少,中间几个年龄段的人又非常多,在 Map 阶段就会造成有些任务很大,有些任务很小。那通过 distribute by 一个均匀字段,就可以让系统均匀地进行“分桶”,对每个桶进行排序,最后再组合,这样就能从整体上提升 MapRece 的效率。

取出 user_trade 表中全部支付用户:

原有写法的执行时长:

优化写法的执行时长:

考虑对之前的案例进行优化:

注意: 在极大的数据量(且很多重复值)时,可以先 group by 去重,再 count() 计数,效率高于直接 count(distinct **) 。

如果我们想知道用户的性别分布、城市分布、等级分布,你会怎么写?

通常写法:

缺点 :要分别写三次SQL,需要执行三次,重复工作,且费时。

那该怎么优化呢?

注意 :这个聚合结果相当于纵向地堆在一起了(Union all),分类字段用不同列来进行区分,也就是每一行数据都包含 4 列,前三列是分类字段,最后一列是聚合计算的结果。

GROUPING SETS() :在 group by 查询中,根据不同的维度组合进行聚合,等价于将不同维度的 group by 结果集进行 union all。聚合规则在括号中进行指定。

如果我们想知道用户的性别分布以及每个性别的城市分布,你会怎么写?

那该怎么优化呢?

注意: 第二列为NULL的,就是性别的用户分布,其余有城市的均为每个性别的城市分布。

cube:根据 group by 维度的所有组合进行聚合

注意 :跑完数据后,整理很关键!!!

rollup:以最左侧的维度为主,进行层级聚合,是cube的子集。

如果我想同时计算出,每个月的支付金额,以及每年的总支付金额,该怎么办?

那应该如何优化呢?

条条大路通罗马,写SQL亦是如此,能达到同样效果的SQL有很多种,要学会思路转换,灵活应用。

来看一个我们之前做过的案例:

有没有别的写法呢?

Hive 中互相没有依赖关系的 job 间是可以并行执行的,最典型的就是
多个子查询union all。在集群资源相对充足的情况下,可以开启并
行执行。参数设置: set hive.exec.parallel=true;

时间对比:

所谓严格模式,就是强制不允许用户执行3种有风险的 HiveSQL 语句,一旦执行会直接报错。

要开启严格模式,需要将参数 hive.mapred.mode 设为 strict 。

好啦,这节课的内容就是这些。以上优化技巧需要大家在平时的练习和使用中有意识地去注意自己的语句,不断改进,就能掌握最优的写法。

5. PLSQL数据库权限基础笔记(GRANT,REVOKE)

权限包括:

SELECT 

INSERT

UPDATE[(col1,col2)]; 可以加括号表示只赋予特定列的权限

DELETE

ALTER

ALL PRIVILEGES

...

CREATE INDEX

CREATE TABLE

ALL PRIVILEGES

...

PUBLIC 关键字可以替换用户名 代表全体用户

ALL 关键字替代权限 代表所有权限

WITH GRANT OPTION 表示 赋予用户权限的权限

GRANT OPTION FOR表示撤销赋予用户权限的权限

我们可以把权限赋予角色 然后将角色赋予用户 简化操作。

创建角色

CREATE ROLE ROLENAME;

GRANT 权限 ON 表名 TO 角色;

将角色赋予用户

GRANT ROLENAME TO USERNAME;

GRANT CONNECT TO laurent IDENTIFIED BY motDePasse

6. MySQL笔记1select基础

查询语句:select 语句
三种能力:投影、选择、连接
投影:在一张二维表中根据所需要的条件选出所需要的列

选择:在二维表中根据所需的条件选择合适的行

连接:从一张或者多张表中获取所需要的行,并且把这个行结合在一起的查询

SQL语句大小写不敏感。

select语句是可以计算的
算术表达式和运算符优先级

举例:select ename,sal 12*sal+100 from emp

计算出年薪+100块

NULL值是不可用,且未分配的,未知并且不适用的值,可以当成是保留值

AS其实可以省略

例如:select ename as name,sal salary from emp;

查询出的字段会自动换成别名
例子:select ename "Name",sal*12 "Annual Salary" from emp;

级联操作是将列或字符串和其他列串联,由两条竖线(||)表示
select ename,job,ename || job as "Employees" from emp;

可以看出Employees就将ENAME和JOB进行结合的一个操作

在select句子中适用DISTINCT 关键字消除重复行
select distinct deptnp from emp;

限制选择的行:
where关键字
如果where后面查的数据是字符串类型或者日期类型的要加''号
#######比较条件

举几个例子:
select ename,job,sal,deptno from emp where sal between 5000 and 10000;

这个是包含了5000和10000的

in的表达:
select empno,ename,mgr,deptno from emp where mgr in (7788,7782,7000);

只要mgr有括号里面的值都显示出来。

通配符:%通配的是多个字符,_通配的是一个字符

IS NULL是查询某个字段为空的显示出来

and、or、not
例子:

查询sal>=2000和job的内容是包括MAN字符串的,当同时满足两个条件时候才返回结果。

and就是两边同时为真,or的话是有一边为真就行,not就是不等于

ASC 升序,默认升序
DESC 降序
例子:

将deptno中进行升序排列,排列出来后,在将sal进行降序排列。

单行函数:就是对单行数据进行处理的函数,只针对这一条数据得出一个结果
函数工作的过程

ROUND(45.926,2)是将45.926这个数字的小数点后两位进行四舍五入操作得到45.93
TRUNC(45.926,2) 是将45.926这个数字的小数点后两位后面的进行丢掉。

返回当前系统日期

经常是不同类型之间的转换

TO_CHAR就是将日期型数字型转换成字符型
例子:

数字型的转换

把字符转换成数字:

把字符转换成日期:

什么是分组函数?
另外的名字叫多行函数,针对于多行数据进行一个汇总处理的一类函数,最后会得到一个汇总的结果。
例子:

其实就是对一系列数据找最大值

基本格式:select group_function(column),... from table [where condition];

首先对一个数据进行分类汇总把每一组的数据单独的拿出来。就是对每一列数据的相同数据进行一个分组,然后在将分组后的结果再去执行select后面跟的一个分组函数的操作。
例子:

那下面这样的怎么操作呢?

其实就是对分组以后的结果再次进行一个限制筛选

where和Having的区别?
where是针对于整体的一个查询结果
Having是针对于分组后的查询结果的一个条件限制,它是不能单独存在的,它只能够在group by后面
下面是它的表达式:

显示部门的最大平均薪水是多少
select max(avg(sal))
是这样的一个嵌套

当我们查的数据存在于多个表的时候就需要多表查询

下面是用到的表

一个是EMP的职员表、一个是DEPT的部分表

表连接的三种方式:
从总类上来看:自连接、等值连接、外连接(又可以分为三类:左连接、右连接、全连接)

自连接:一个表自己与自己建立连接成为自连接或自身连接。
在查询的时候多表,这两张表是同一张表,所以在查询前我们需要对这个表进行一个别名的重命名。
举例:查询出员工编号、名字及其经理名字

MGR对应的是经理的ID号,这个对应的就是另一张经理表中的名字

表示比较连接列的值显示出最终的一个结果,其查询结果中列出被连接表中的所有列,包括其中的重复列。
查询员工的姓名 工作 部门号 部门名称

左连接就是返回左边的匹配行,不考虑右边的表是否有相应的行

(+)的意思就是dept是个匹配表,左边是一个基础表,基础表优先,如果右边这个表找不到对应的值去匹配,会自动填空

右连接就是返回右边的匹配行,不考虑左边的表是否有相应的行,如果没有会自动填空

左表右表都不做限制,所有的记录都显示,不足的地方用null填充

FULL JOIN表示emp和dept做一个全连接
ON表示触发条件 。

7. 数据库笔记-SQL过滤(LIKE&正则表达式)

查询语句:

结果:

查询语句:

结果:

查询语句:

结果:

查询语句:

正则表达式 [32]1,[32]定义一组字符,它的意思是匹配 3 或匹配 2,也就是“31”或者 “21”都算是匹配的。

结果:

查询语句:

结果:

如果要匹配特殊字符的,需要加上前导“”,“-”表示查找“-”,“.”表示查找“.”
这种就是 “转义(escaping)” ,在正则表达式里,本身有意义的字符,比如“.”是匹配任意字符的意思。那如果要匹配它,需要转义。
注意:在 MySQL 里,是比其他的正则表达式多一个“”的,就是“”。

趣味提问:

如何匹配“”?
答案:“\”

\([0-9] sticks?\) 匹配的是(NUM stick)或者(NUM sticks)。s后的 ? 使得s可选。

重复元字符

* 是 0 个或多个匹配
? 是 1 个或多个匹配
{n} 是指定n个匹配
{n,} 是 不少于 n 个匹配
{n,m} 是 指定匹配的范围,m不超过 255

查询语句:

^值的是字符串的开始,$是字符串的结尾。

这就是 REGEXP 与 LIKE 类似,但是它独特的好处:可以通过“定位符”只匹配“子字符串”。

结果:

8. 如何在SQL表中的性别进行check约束

1、下面打开SQL SERVER查看一下要操作的表的数据结构。

9. SQL中EXISTS怎么用

EXISTS在SQL中的作用是:检验查询是否返回数据。

select a.* from tb a where exists(select 1 from tb where name =a.name)返回真假,当 where 后面的条件成立,则列出数据,否则为空。

exists强调的是是否返回结果集,不要求知道返回什么。比如:select name from student where sex = 'm' and mark exists(select 1 from grade where ...)

只要exists引导的子句有结果集返回,那么exists这个条件就算成立了,大家注意返回的字段始终为1

如果改成“select 2 from grade where ...”,那么返回的字段就是2,这个数字没有意义。所以exists子句不在乎返回什么,而是在乎是不是有结果集返回。

(9)SQL解惑笔记扩展阅读:

Exists 方法描述如果在 Dictionary对象中指定的关键字存在,返回True,若不存在,返回False。

语法object.Exists(key)Exists 方法语法有如下几部分:部分描述Object必需的。始终是一个 Dictionary对象的名字。Key必需的,在 Dictionary对象中搜索的Key值。

exist相当于存在量词:表示集合存在,也就是集合不为空只作用一个集合.

例如 exist P表示P不空时为真; not exist P表示p为空时为真in表示一个标量和一元关系的关系。

例如:s in P表示当s与P中的某个值相等时为真; s not in P 表示s与P中的每一个值都不相等时为真。

exits与not exits

exists(sql 返回结果集为真)

not exists(sql 不返回结果集为真)

如果not exists子查询只有自己本身的查询条件,这样只要子查询中有数据返回,就证明是false,结果在整体执行就无返回值;一旦跟外面的查询关联上,就能准确查出数据。

10. sql查询两个字段相同的记录

EXCEL中用VBA连接ACCESS数据库
有如下一张表,要分别查找出所有同名的人、所有同名并且学号也一样的人以及所有同名但不同学号的人。

查询所有同名人员
select * from [18年考试成绩] where [姓名] in (SELECT [姓名] FROM [18年考试成绩] group by [姓名] having count(姓名)>1)
查询结果:

查找所有姓名和学号两个字段都重复的人
select * from [18年考试成绩] where [姓名] in (SELECT [姓名] FROM [18年考试成绩] group by [姓名] having count(姓名)>1) and [学号] in (SELECT [学号] FROM [18年考试成绩] group by [学号] having count(学号)>1)
查询结果:

查找所有姓名重复但学号不重复的人
select * from [18年考试成绩] where [姓名] in (SELECT [姓名] FROM [18年考试成绩] group by [姓名] having count(姓名)>1) and [学号] not in (SELECT [学号] FROM [18年考试成绩] group by [学号] having count(学号)>1)
注意:要把SELECT查询子句配合in或not in 操作符使用,SELECT查询子句只能有一列内容。
查询结果:

其中子句 “SELECT [姓名] FROM [18年考试成绩] group by [姓名] having count(姓名)>1”是显示所有重复的姓名,如果如下:

如果要知道重复出现次数,则可以这样写:
SELECT [姓名],count(姓名) as 出现次数 FROM [18年考试成绩] group by [姓名] having count(姓名)>1
结果如下:

查找唯一记录
group by [姓名],意思是按姓名分组,having count(姓名)>1 是分组条件,意思是姓名次数出现2次以上的重复内容以姓名进行分组,前面的count(姓名)是对分组以后的姓名统计出现次数。在后面要使用函数条件时应该使用having,而不是使用where
查找唯一值,比如本例的班级中,只有一个“四班”,要把这个四班的所有字段显示出来可以这样:
select * from [18年考试成绩] where 班级 not in (SELECT 班级 FROM [18年考试成绩] group by 班级 having count(班级)>1)
结果:

如果使用“SELECT DISTINCT 班级 FROM [18年考试成绩]”语句查询唯一值,结果将会如下:

DISTINCT 会显示不重复的值,如果有重复的,只显示第一个,所以如果需要显示仅出现一次的值并不适合使用SELECT DISTINCT语句
分组查询语句:
比如要班级为单位,查询每个班的总人数,科目总分,科目平均分等
SELECT [班级],count(姓名) as 班级人数,sum(语文) as 语文总成绩,sum(数学) as 数学总成绩,ROUND(avg(语文),1) as 语文平均分,ROUND(avg(数学),1) as 数学平均分 FROM [18年考试成绩] group by [班级]
查询结果如下:

注意:如果使用函数的字段,不使用AS指定别名,将会自动生成一个字段名,第一列名字Expr1000,第二列名为Expr1001,第三列名为Expr1002,以此类推
如:
SELECT [班级],count(姓名),sum(语文),sum(数学),ROUND(avg(语文),1) ,ROUND(avg(数学),1) FROM [18年考试成绩] group by [班级]
查询结果如下:

如果不指定别名,你将无法清楚在查询结果中知道每一列是干什么的。
如果需要再细分,查询每个班女生总人数和科目平均分,只需要再加一个where条件就可以了
SELECT [班级],count(姓名) as 班级女性人数,ROUND(avg(语文),1) as 语文平均分,ROUND(avg(数学),1) as 数学平均分 FROM [18年考试成绩] where 性别='女' group by [班级]