当前位置:首页 » 编程语言 » 怎么解释sql做数据分析
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

怎么解释sql做数据分析

发布时间: 2023-04-11 09:58:33

‘壹’ sql语句对数据分析重要吗

楼主好,SQL对数据分析相当重要,我当前就入行了数据分析行业。其实说白了所谓数据分析,首先要有数据,而你写的SQL就成了数据。其实换到数据分析行业中讲,你要分析首先就要有数据仓库和数据集,而如何能得到这些数据,就全是SQL写出来的,然后通过工具加载到固定的数据库中,就得到了数据仓库。就算是你在做分析类型的报表,也全部都是SQL语句写出来,得到数据,加载到报表中的。数据挖掘也是要获取到数据的,当然也是SQL。所以想要做数据分析,SQL是必须过关的。

‘贰’ 数据分析人必掌握的数据库语言-SQL指南第六期

本篇文章继续围绕SQL的语法重点为大家介绍 连接 高级连接 的使用,以及 使用连接的注意事项



SQL最强大的功能之一就是能在数据查询的执行中 连接(join)表 。连接是利用SQL的SELECT语句能执行的最重要的操作,很好地理解连接及其语法是学习SQL的极为重要的一点。在能够有效地使用连接前,我们必须了解 关系表 以及 关系数据库 设计的一些基础知识。下面的介绍并不能涵盖这一主题的所有内容,但作为入门已经够了。


连接

理解关系表,最好是来看个例子。

有一个包含产品目录的数据库表,其中每类物品占一行。

对于每一种物品,要存储的信息包括产品描述、价格,以及生产该产品的供应商。

现在有同一供应商生产的多种物品,那么在何处存储供应商名、地址、联系方法等供应商信息呢?将这些数据与产品信息分开存储的理由是:

同一供应商生产的每个产品,其供应商信息都是相同的,对每个产品重复此信息既浪费时间又浪费存储空间;

如果供应商信息发生变化,例如供应商迁址或电话号码变动,只需修改一次即可;

如果有重复数据(即每种产品都存储供应商信息),则很难保证每次输入该数据的方式都相同。不一致的数据在报表中就很难利用。

关键是, 相同的数据出现多次不是一件好事 ,这是关系数据库设计的基础。

关系表的设计就是要 把信息分解成多个表 一类数据一个表 。各表通过某些共同的值互相关联(所以才叫关系数据库)。在这个例子中可建立两个表:一个存储供应商信息,另一个存储产品信息。Vendors表包含所有供应商信息,每个供应商占一行,具有唯一的标识。此标识称为 主键 (primary key),可以是供应商ID或任何其他唯一值。Procts表只存储产品信息,除了存储供应商ID(Vendors表的主键)外,它不存储其他有关供应商的信息。Vendors表的主键将Vendors表与Procts表关联,利用供应商ID能从Vendors表中找出相应供应商的详细信息。

这样做的 好处 是:

供应商信息不重复,不会浪费时间和空间;

如果供应商信息变动,可以只更新Vendors表中的单个记录,相关表中的数据不用改动;

由于数据不重复,使得处理数据和生成报表更简单。

总之,关系数据可以有效地存储,方便地处理。因此,关系数据库的可伸缩性远比非关系数据库要好。


为什么使用连接

连接将数据分解为多个表实现 更有效 地存储、 更方便 地处理,且 可伸缩性更好

可伸缩性:能够适应不断增加的工作量而不失败。

连接作为一种机制,能在一条SELECT语句中用来关联表。使用特定的语法,可连接多个表返回一组输出。


创建连接

分析 :上述SELECT语句中与之前的语句相同,都是指定检索的列, 区别 在于该语句指定的两列(prod_name,prod_price)在一个表中,而第一列(vend_name)在另一个表中。

FROM子句也有所区别。该FROM子句列出了两个表:Vendors,Procts。这两个表由SELECT语句的WHERE子句连接。WHERE子句指示DBMS将Vendors表中的vend_id与Procts表中的vend_id匹配起来。

这里使用了 完全限定列名 将Vendors.vend_id和Procts.vend_id两列匹配。最终输出了两个不同表中的数据。



高级连接部分将介绍 如何使用表别名,另外的一些连接 ,以及 如何对被连接的表使用聚集函数


使用表别名

之前的文章已经给大家介绍了如何使用别名引用被检索的表列。

SQL还可以 给表名起别名 ,目的是:

缩短SQL语句。

允许在一条SELECT语句中多次使用相同的表。

分析 :上述语句中的FROM子句的三个表都有别名。如此 省略了许多字符 。表别名还可以用于SELECT的列表、ORDER BY子句以及其他语句部分。

需要注意的是: 表别名只在查询执行中使用 。与列别名不同,表别名不返回到客户端。


使用不同类型的连接

接下来将给大家介绍四种其他类型的连接: 自连接 自然连接 内连接 外连接

①自连接

分析: 这是使用了 子查询 的方案。对内部的SELECT语句做了一个简单的检索,返回Jim Jones工作公司的cust_name。该数据用于外部查询的WHERE子句中,以检索出为该公司工作的所有雇员。

下面看看使用了 连接 的方案。

分析:上述语句需要的两个表实际上是相同的表,所以Customers表在FROM子句中出现了两次。但这对于Customers的引用具有歧义,因为没有指示DBMS引用的是哪个Customers表。

于是需要使用表别名解决该问题。Customers表 第一次出现为别名c1 第二次为c2 ,然后再将这些别名用作表名。如SELECT语句使用c1前缀明确给出所需列的全名。如果不这么做,DBMS将返回错误,因为名为cust_id、cust_name、cust_contact的列各有两个。DBMS不知需要哪一列,即使它们都是同一列。

WHERE首先连接两个表,再按第二个表中的cust_contact过滤数据,返回所需的数据。


②自然连接

内连接 返回所有的数据,其中 相同的列可多次出现 。而 自然连接排除多次出现 ,使每一列只返回一次。

一般通过对一个表使用通配符(SELECT *),而对其他的列使用明确的子集来实现自然连接。

分析: 上述语句中,通配符只对第一个表使用,而所有其他列都明确列出来,所以没有出现重复的列被检索出来。


③内连接

目前为止使用的连接称为等值连接,是基于两个表之间的相等测试。该连接也称为内连接。

对该种连接还可以使用不同的语法,明确指定连接的类型。

分析 :该语句中的SELECT与之前的区别在于FROM 子句。此处两个表之间的关系是以 INNER JOIN 指定的部分FROM子句,因此需要使用特定的 ON子句 而不是WHERE子句。但传递给ON的实际条件与WHERE相同。


④外连接

许多连接将一个表中的行与另一个表中的行相关联,但有时候 需要包含没有关联的行 。例如,可能需要使用连接完成以下工作:

对每个顾客下的订单进行计数,包括那些至今尚未下订单的顾客;

列出所有产品以及订购数量,包括没有人订购的产品;

计算平均销售规模,包括那些至今尚未下订单的顾客。

在上述例子中,连接包含了那些在相关表中没有关联行的行。这种连接称为外连接,外连接分为 左外连接 右外连接

左外连接:取左边的表的全部,而右边的表按照条件显示,不符合条件的显示NULL。

右外连接:取右边的表的全部,而左边的表按照条件显示,不符合条件的显示NULL。

下面先给出一个简单的 内连接 ,再给出 左外连接 ,大家对比着理解。

分析 :两个语句都使用了 JOIN 关键字来指定连接类型,与内连接不同的是,左外连接包括没有关联行的行。因此在使用JOIN语法时,还需使用RIGHT或LEFT关键字来指定包括其所有行的表(RIGHT指出的是OUTER JOIN右边的表,而LEFT指出的是OUTER JOIN左边的表)。

上述左外连接语句使用了LEFT OUTER JOIN 从FROM子句左边的表(Customers)中选择所有行。

若要从右边的表选择所有行,即使用 右外连接 ,则语句如下:

注意 :两种基本的外连接形式,左外连接和右外连接。两者的唯一差别是所关联的表的顺序。

此外,还有一种外连接,即 全外连接 。该连接检索两个表中的所有行并关联可关联的行。与左外连接或右外连接包含一个表的不关联的行不同,全外连接包含两个表的不关联的行。


自连接、自然连接、内连接和外连接的区别

①自连接: 通常用于 两张结构和数据内容完全一样的表 ,在做数据处理时,对它们分别 重命名 来加以区分,然后再进行关联。

②自然连接 :特点是要求两个关系表中进行连接的必须是 相同属性列 (名字相同),无需添加连接条件,且 在结果中消除了重复的属性列

③内连接 :与自然连接相似,区别在于内连接 不要求两属性列同名 ,可以用 using或on 来指定某两列字段相同的连接条件。

④外连接 :可以解决自然连接时某些属性不同导致这些元组被舍弃的问题,起到了 保留要舍弃的结果 的作用。


使用带聚集函数的连接

之前给大家介绍过使用 聚集函数 来汇总数据,殊不知这些函数也可以与连接一起使用。

分析: 上述语句使用了 COUNT函数 。该语句使用INNER JOIN将Customers和Orders表相互关联。GROUP BY子句按顾客分组,因此,函数调用COUNT(Orders.order_num)对每个顾客的订单计数,将其作为num_ord返回。

分析: 上述语句使用 左外连接 包含所有顾客,包括了那些没有任何订单的顾客。



WHERE子句的重要性

需记住的是,在一条SELECT语句中连接几个表时,相应的关系是在运行中构造的,因为在数据库表中的定义没有指示DBMS如何对表进行连接的内容。

要连接多个表,需要将它们并列于from之后, 关键 是要设置WHERE子句,确保它们之间的 关联关系 必须给出,否则,查询结果会成为笛卡尔积。

笛卡尔积:由没有连接条件的表关系返回的结果为笛卡儿积。

分析 :上述语句输出的结果便是 笛卡尔积 。返回的数据用每个供应商匹配了每个产品,包括了供应商不正确的产品(即使该供应商没有产品)。


连接及其使用的要点

注意所使用的连接类型。一般我们使用内连接,但使用外连接也有效。

关于确切的连接语法,应该查看具体的文档,看相应的DBMS支持何种语法(大多数DBMS使用这两课中描述的某种语法)。

保证使用正确的连接条件(不管采用哪种语法),否则会返回不正确的数据。

应该总是提供连接条件,否则会得出笛卡儿积。

在一个连接中可以包含多个表,甚至可以对每个连接采用不同的连接类型。虽然这样做是合法的,一般也很有用,但应该在测试它们前分别测试每个连接。这会使故障排除更为简单。

以上就是本次介绍的连接和高级连接啦~

下一期将给大家介绍 组合查询 插入数据 更新和删除数据。

我们下期见!

‘叁’ 什么是数据分析如何学习数据分析

【导读】无论是从薪资待遇还是未来的发展前景,数据分析师都是屈指可数的稀缺人才,那么什么是数据分析?如何学习数据分析呢?下面跟着小编一起来分析一下吧!

什么是数据分析?

对于数据分析的概念,我们需要有一个深刻的理解。数据分析是指用适当的统计分析方法对收集来的大量数据进行分析,将它们加以汇总和理解并消化,以求最大化地开发数据的功能,发挥数据的作用。

如何学习数据分析?

的确,兴趣能作为你学习下去的动力,但是后续不断地学习并掌握技能才是根配拍本。小编以前特别喜欢吉他,于是就报了吉他班。弹吉他确实是一件很酷的事,但是学习过程却非常艰辛。我的手指尖经常因为手运弹吉他生成黄黄的老茧。有时候我甚至想要放弃,但是在培薯羡老师和父母的监督下,我还是坚持了下来。

学习数据分析的过程何尝不是如此呢?想要实现梦想,就一定要付诸汗水。以下便是小编为小白们提的几点学习数据分析的建议~

1.浏览各大平台有关数据分析的论坛。

很多技术大牛在网络贴吧、知乎、B站、CSDN等平台都发布过自己的经验贴,积少成多的知识可以帮助我们少走很多弯路,从而更快地掌握知识。

2.运用数据集开启项目。

感兴趣的小伙伴可以点击下方链接康康小编推荐过的数据集~

3.掌握数据分析师的必备技能。

(1)Excel。很多人的电脑里都安装了Excel这款软件。在办公时,我们经常会用Excel制作表格。除此之外,Excel还是一款数据管理工具,可以用于数据的清理、分析和可视化。

(2)SQL。SQL是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。

(3)Tableau等可视化软件。Tableau这一款可视化工具广泛运用于商业领域。并且,Tableau是一款自带教程的软件,省去了我们去别的平台找学习视频的时间。

以上就是小编今天给大家整理发送的关于“什么是数据分析?如何学习数据分析?”的相关内容,希望对大家有所帮助。小编认为要想在大数据行业有所建树,需要考取部分含金量高的数据分析师证书,这样更有核心竞争力与竞争资本。

‘肆’ 用SQL做简单数据分析(入门级)

你要的分析功能已经有智能分析的要求了
这超出了sql现有的功能 ,只用sql语句是无法直接打到这种分析的

‘伍’ 详细讲解如何用SQLyog来分析MySQL数据库

我去了相关网站下载,它只有384K字节大小。它把两个文件(一个可执行文件.exe和一个动态链接库文件.dll)安装到C:\Program Files\SQLyog路径下。然后运行可执行文件。 安装后没有必要再访问该网站了,我访问该网站是得到了一个消息,说它的域名没有设置(configured)、登记、或正在建设中。我不清楚这个问题是暂时的还是一直是这样。该软件是免费的,并且没有标志广告(banner ads),所以它可能是一个特定的尚未最终定型的商业模型。最终可能还是要负费的。 数据库、表格(table)和列树(column tree)该程序一启动就开始询问我的登录到MySOL服务器的口令。我只需要输入我的服务器名字、用户id和登录密码。所有其它的设置都是正确的默认值。然后(当我开始其它事务、弊磨重启几次、睡了一会之后),我重新运行该程序,这时只需要再次输入我的登录密码。该程序没有保存密码的选项,你可以认为这是该程序的一个bug,也可以说是程序的保密特性。 一旦你登录之后,界面就是很值得注意。MySOL服务器上所有的数据库都显示在一个树型控件上。你只能访问你在登录时授权的那个数据库。如果你点开代表授权给你的那个数据库的树型结构,你就可以看到一系列代表表格的节点。点开表格节点后,你就可以看到一系列显示字段名的节点和另一个代表索引的节点集合。 索引界面绝对是个好东东,这迟卜扒样你就可以CRUD查询索引和关键字了。这相对前端数据库如Microsoft Access来说是个提高。如果考虑到MySOL刚刚开始提供对主(primary)和非相关(foreign)关键字关系的支持,本程序这部分的设计是很成熟的。在右下方的面板上,有四个标签页,即:结果(Result)、消息(Message)、对象(Object)和历史(History)。 有什么缺点?我试图发现该程序的缺点,不过只发现了一个。如果你在Win32 Dependency Walker下运行程序的.exe文件,你会发现它引用了COMDLG32.dll文件,码昌而COMDLG32.dll又轮流引用AppHelp。实事上,CommDlg调用AppHelp,而当AppHelp没有请求函数时,CommDlg这么做根本就是浪费资源。 过于简单?在SQLyog FAQ上,有一种观点认为该软件没有正式归档的必要。当然,FAQ(常见问题解答)本身就是一种归档。SQLyog的界面非常直观。我建议你打印一份MySOL文档(包括SQL特殊语法扩展)。我就是这么做的,它只用了一个半英寸的活页封面。 最后一步?FAQ还让人想到一个让人耳朵起了老茧却又是正确的Occam's Razor准则——一切超出必要的复杂性都是没有必要的。我之所以到处“推销”这个工具,就是因为它可以为我们提供一个可以管理MySOL服务器上许多数据库的、简单的、图形化的界面。它的速度极快,并且它的拷贝很小(可以放在一张软盘上)。

‘陆’ 数据分析过程如果用SQL语句进行统计如何实现

方法和详细的操作步骤如下:

1、第一步,创建一个测试表,详细代码见下图,转到下面的步骤。

‘柒’ 数据分析人必掌握的数据库语言-SQL指南第五期

本篇文章继续围绕SQL的语法重点为大家介绍 子查询 的使用。



使用子查询进行过滤

在SQL中SELECT语句用于查询,之前所使用的所有SELECT语句都是简单查询,即从单个数据库表中检索数据的单条语句。然而SQL还可以创建子查询,即嵌套在其他查询中的查询。

示例:

数据表:本次使用的数据库表都是 关系表 。订单存储在两个表中,每个订单包含订单编号、客户ID、订单日期,在Orders表中存储为一行。各订单的物品存储在相关的OrderItems表中。Orders表不存储顾客信息,只存储顾客ID。顾客实际信息存储在Customers表中。

若现在需要检索出订购RGAN01的所有顾客,应怎样检索? 步骤如下:

检索包含物品RGAN01的所有订单的编号。

检索具有前一步骤列出的订单编号的所有顾客的ID。

检索前一步骤返回的所有顾客ID的顾客信息。

上述每个步骤都可 单独作为一个查询 来进行。

可将一条SELECT语句返回的结果用于另一条SELECT语句的WHERE子句,也可使用 子查询 来将3个查询组合成一条语句。

第一个语句含义明确,是对prod_id为RGAN01的所有订单物品检索其order_num列。

分析: 通过该语句知道了哪个订单包含要检索的物品。

下一步查询与上述语句检索出的订单20007和20008相关的顾客ID。此处可利用IN子句。

下面可结合上述两个查询,将第一个查询变为子查询。

分析:在SELECT语句中, 子查询总是从内向外处理 。在处理上述SELECT语句时,DBMS实际上执行了两个操作。

首先执行了 圆括号()内的查询 ,此查询返回两个订单号: 20007 20008 .

接着这两个值以IN操作符要求的逗号分隔的格式传递给外部查询的WHERE子句。 外部查询变为:

该语句检索的结果和前面硬编码WHERE子句返回的结果相同。

由上述语句得出订购物品RGAN01的所有顾客ID: 100004 100005 .下一步检索这些顾客ID的顾客信息。

也可将其中的WHERE子句转换为子查询,就不用硬编码这些顾客ID了。

分析: DBMS实际上必须执行三条SELECT语句才能完成上述语句。最里面的子查询返回订单号,此列用于外面的子查询的WHERE子句。外面的子查询返回顾客ID列,此顾客ID列用于最外层查询的WHERE子句。最外层查询返回最终所需的数据。

由此可见,在WHERE子句中使用子查询可编写出功能强大灵活的SQL语句。对于能嵌套的子查询的数目没有限制,不过在实际应用中由于 性能的限制 ,不宜嵌套太多子查询。

注意: 作为子查询的SELECT语句只能查询 单个列 ,检索多个列将返回错误。另外使用子查询并不总是执行该类数据检索的最有效方法。


作为计算字段使用子查询

使用子查询的另一方法是创建计算字段。

示例: 需要显示Customers表中每个顾客的订单总数。订单与相应的顾客ID都存储在Orders表中。要执行这个操作,需要以下步骤:

从Customers表中检索顾客列表。

对于检索出的每个顾客,统计其在Orders表中的订单数目。

这里我们可以应用之前介绍的 SELECT COUNT(*) 对表中的行进行计数,并通过一条WHERE子句来过滤某个特定的顾客ID,仅对该顾客的订单进行计数。

如下对顾客1000001的订单进行计数:

要对每个顾客执行COUNT(*)需要将其作为一个子查询,如下:

分析: 该SELECT语句对Customers表中的每个顾客返回三列:cust_name、cust_state和orders。orders是一个 计算字段 ,它由圆括号中的子查询建立。该子查询对检索出的每个顾客执行一次。此例中, 该子查询执行了5次 ,因为检索出了5个顾客。

子查询中的WHERE子句与之前使用的WHERE子句略有不同,因为它使用了 完全限定列名 ,而不只是列名(cust_id)。它指定表名和列名(Orders.cust_id和Customers.cust_id)。下面的WHERE子句告诉SQL,比较Orders表中的cust_id和当前正从Customers表中检索出的cust_id:

在有可能混淆列名时必须用一个 句点分隔表名和列名 。此例中,有两个cust_id列:一个在Customers中,另一个在Orders中。若不采用完全限定名,DBMS会认为要对Orders表中的cust_id自身进行比较。因为:

上述语句总返回Orders表中订单的总数,而该 结果不是我们想要的 ,如下:

由上可知,在构造语句时,若涉及到多个表,而不对同一列名加以区分则会引起DBMS抛出错误信息。

好的做法是,当在SELECT语句中操作多个表时, 使用完全限定列名来避免歧义

最后总结一下子查询的特点:

子查询必须括在圆括号中。

子查询的SELECT子句中只能有一个列,除非主查询中有多个列,用于与子查询选中的列相比较。

子查询不能使用ORDER BY,不过主查询可以。在子查询中,GROUP BY可以起到同ORDER BY相同的作用。

返回多行数据的子查询只能同多值操作符一起使用,比如IN操作符。

SELECT 列表中不能包含任何对BLOB、ARRAY、CLOB或者NCLOB类型值的引用。

子查询不能直接用在聚合函数中。

BETWEEN操作符不能同子查询一起使用,但是BETWEEN操作符可以用在子查询中。

以上便是本次介绍的全部内容,下篇文章将为大家讲解 连接 高级连接 的使用。

我们下期再见!

‘捌’ SQL数据库语言分析

ALTER TABLE Customer_Data
ADD middle_initial char(1)
GO
这个本来就是一条执行语句 ...
意思是给表Customer_Data添加一个字段名为middle_initial的字段, 类型为CHAR,长度为1
至GO 写不写都行

‘玖’ SQL语句执行流程与顺序原理解析

SQL语句执行流程与顺序原理解析
Oracle语句执行流程
第一步:客户端把语句发给服务器端执行
当我们在客户端执行SQL语句时,客户端会把这条SQL语句发送给服务器端,让服务器端的进程来处理这语句。也就是说,Oracle 客户端是不会做任何的操作,他的主要任务就是把客户端产生的一些SQL语句发送给服务器端。服务器进程从用户进程把信息接收到后, 在PGA 中就要此进程分配所需内存,存储相关的信息,如:在会话内存存储相关的登录信息等。
虽然在客户端也有一个数据库进程,但是,这个进程的作用跟服务器上的进程作用是不相同的,服务器上的数据库进程才会对SQL 语句进行相关的处理。不过,有个问题需要说明,就是客户端的进程跟服务器的进程是一一对应的。也就是说,在客户端连接上服务器后,在客户端与服务器端都会形成一个进程,客户端上的我们叫做客户端进程,而服务器上的我们叫做服务器进程。
第二步:语句解析
当客户端把SQL语句传送到服务器后,服务器进程会对该语句进行解析。这个解析的工作是在服务器端所进行的,解析动作又可分为很多小动作。
1)查询高速缓存(library cache)
服务器进程在接到客户端传送过来的SQL语句时,不会直接去数据库查询。服务器进程把这个SQL语句的字符转化为ASCII等效数字码,接着这个ASCII码被传递给一个HASH函数,并返回一个hash值,然后服务器进程将到shared pool中的library cache(高速缓存)中去查找是否存在相同的hash值。如果存在,服务器进程将使用这条语句已高速缓存在SHARED POOL的library cache中的已分析过的版本来执行,省去后续的解析工作,这便是软解析。若调整缓存中不存在,则需要进行后面的步骤,这便是硬解析。硬解析通常是昂贵的操作,大约占整个SQL执行的70%左右的时间,硬解析会生成执行树,执行计划,等等。
所以,采用高速数据缓存的话,可以提高SQL 语句的查询效率。其原因有两方面:一方面是从内存中读取数据要比从硬盘中的数据文件中读取数据效率要高,另一方面也是因为避免语句解析而节省了时间。
不过这里要注意一点,这个数据缓存跟有些客户端软件的数据缓存是两码事。有些客户端软件为了提高查询效率,会在应用软件的客户端设置数据缓存。由于这些数据缓存的存在,可以提高客户端应用软件的查询效率。但是,若其他人在服务器进行了相关的修改,由于应用软件数据缓存的存在,导致修改的数据不能及时反映到客户端上。从这也可以看出,应用软件的数据缓存跟数据库服务器的高速数据缓存不是一码事。
2)语句合法性检查(data dict cache)
当在高速缓存中找不到对应的SQL语句时,则服务器进程就会开始检查这条语句的合法性。这里主要是对SQL语句的语法进行检查,看看其是否合乎语法规则。如果服务器进程认为这条SQL语句不符合语法规则的时候,就会把这个错误信息反馈给客户端。在这个语法检查的过程中,不会对SQL语句中所包含的表名、列名等等进行检查,只是检查语法。
3)语言含义检查(data dict cache)
若SQL 语句符合语法上的定义的话,则服务器进程接下去会对语句中涉及的表、索引、视图等对象进行解析,并对照数据字典检查这些对象的名称以及相关结构,看看这些字段、表、视图等是否在数据库中。如果表名与列名不准确的话,则数据库会就会反馈错误信息给客户端。
所以,有时候我们写select语句的时候,若语法与表名或者列名同时写错的话,则系统是先提示说语法错误,等到语法完全正确后再提示说列名或表名错误。
4)获得对象解析锁(control structer)
当语法、语义都正确后,系统就会对我们需要查询的对象加锁。这主要是为了保障数据的一致性,防止我们在查询的过程中,其他用户对这个对象的结构发生改变。
5)数据访问权限的核对(data dict cache)
当语法、语义通过检查之后,客户端还不一定能够取得数据,服务器进程还会检查连接用户是否有这个数据访问的权限。若用户不具有数据访问权限的话,则客户端就不能够取得这些数据。要注意的是数据库服务器进程先检查语法与语义,然后才会检查访问权限。
6)确定最佳执行计划
当语法与语义都没有问题权限也匹配,服务器进程还是不会直接对数据库文件进行查询。服务器进程会根据一定的规则,对这条语句进行优化。在执行计划开发之前会有一步查询转换,如:视图合并、子查询解嵌套、谓语前推及物化视图重写查询等。为了确定采用哪个执行计划,Oracle还需要收集统计信息确定表的访问联结方法等,最终确定可能的最低成本的执行计划。
不过要注意,这个优化是有限的。一般在应用软件开发的过程中,需要对数据库的sql语句进行优化,这个优化的作用要大大地大于服务器进程的自我优化。
当服务器进程的优化器确定这条查询语句的最佳执行计划后, 就会将这条SQL语句与执行计划保存到数据高速缓存(library cache)。如此,等以后还有这个查询时,就会省略以上的语法、语义与权限检查的步骤,而直接执行SQL语句,提高SQL语句处理效率。
第三步:绑定变量赋值
如果SQL语句中使用了绑定变量,扫描绑定变量的声明,给绑定变量赋值,将变量值带入执行计划。若在解析的第一个步骤,SQL在高速缓冲中存在,则直接跳到该步骤。
第四步:语句执行
语句解析只是对SQL语句的语法进行解析,以确保服务器能够知道这条语句到底表达的是什么意思。等到语句解析完成之后,数据库服务器进程才会真正的执行这条SQL语句。
对于SELECT语句:
1)首先服务器进程要判断所需数据是否在db buffer存在,如果存在且可用,则直接获取该数据而不是从数据库文件中去查询数据,同时根据LRU 算法增加其访问计数;
2)若数据不在缓冲区中,则服务器进程将从数据库文件中查询相关数据,并把这些数据放入到数据缓冲区中(buffer cache)。
其中,若数据存在于db buffer,其可用性检查方式为:查看db buffer块的头部是否有事务,如果有事务,则从回滚段中读取数据;如果没有事务,则比较select的scn和db buffer块头部的scn,如果前者小于后者,仍然要从回滚段中读取数据;如果前者大于后者,说明这是一非脏缓存,可以直接读取这个db buffer块的中内容。
对于DML语句(insert、delete、update):
1)检查所需的数据库是否已经被读取到缓冲区缓存中。如果已经存在缓冲区缓存,则直接执行步骤3;
2)若所需的数据库并不在缓冲区缓存中,则服务器将数据块从数据文件读取到缓冲区缓存中;
3)对想要修改的表取得的数据行锁定(Row Exclusive Lock),之后对所需要修改的数据行取得独占锁;
4)将数据的Redo记录复制到redo log buffer;
5)产生数据修改的undo数据;
6)修改db buffer;
7)dbwr将修改写入数据文件;
其中,第2步,服务器将数据从数据文件读取到db buffer经经历以下步骤:
1)首先服务器进程将在表头部请求TM锁(保证此事务执行过程其他用户不能修改表的结构),如果成功加TM锁,再请求一些行级锁(TX锁),如果TM、TX锁都成功加锁,那么才开始从数据文件读数据。
2)在读数据之前,要先为读取的文件准备好buffer空间。服务器进程需要扫描LRU list寻找free db buffer,扫描的过程中,服务器进程会把发现的所有已经被修改过的db buffer注册到dirty list中。如果free db buffer及非脏数据块缓冲区不足时,会触发dbwr将dirty buffer中指向的缓冲块写入数据文件,并且清洗掉这些缓冲区来腾出空间缓冲新读入的数据。
3)找到了足够的空闲buffer,服务器进程将从数据文件中读入这些行所在的每一个数据块(db block)(DB BLOCK是ORACLE的最小操作单元,即使你想要的数据只是DB BLOCK中很多行中的一行或几行,ORACLE也会把这个DB BLOCK中的所有行都读入Oracle DB BUFFER中)放入db buffer的空闲的区域或者覆盖已被挤出LRU list的非脏数据块缓冲区,并且排列在LRU列表的头部,也就是在数据块放入db buffer之前也是要先申请db buffer中的锁存器,成功加锁后,才能读数据到db buffer。
若数据块已经存在于db buffer cache(有时也称db buffer或db cache),即使在db buffer中找到一个没有事务,而且SCN比自己小的非脏缓存数据块,服务器进程仍然要到表的头部对这条记录申请加锁,加锁成功才能进行后续动作,如果不成功,则要等待前面的进程解锁后才能进行动作(这个时候阻塞是tx锁阻塞)。
在记redo日志时,其具体步骤如下:
1)数据被读入到db buffer后,服务器进程将该语句所影响的并被读入db buffer中的这些行数据的rowid及要更新的原值和新值及scn等信息从PGA逐条的写入redo log buffer中。在写入redo log buffer之前也要事先请求redo log buffer的锁存器,成功加锁后才开始写入。
2)当写入达到redo log buffer大小的三分之一或写入量达到1M或超过三秒后或发生检查点时或者dbwr之前发生,都会触发lgwr进程把redo log buffer的数据写入磁盘上的redo file文件中(这个时候会产生log file sync等待事件)。
3)已经被写入redo file的redo log buffer所持有的锁存器会被释放,并可被后来的写入信息覆盖,redo log buffer是循环使用的。Redo file也是循环使用的,当一个redo file写满后,lgwr进程会自动切换到下一redo file(这个时候可能出现log file switch(check point complete)等待事件)。如果是归档模式,归档进程还要将前一个写满的redo file文件的内容写到归档日志文件中(这个时候可能出现log file switch(archiving needed)。
在为事务建立undo信息时,其具体步骤如下:
1)在完成本事务所有相关的redo log buffer之后,服务器进程开始改写这个db buffer的块头部事务列表并写入scn(一开始scn是写在redo log buffer中的,并未写在db buffer)。
2)然后包含这个块的头部事务列表及scn信息的数据副本放入回滚段中,将这时回滚段中的信息称为数据块的“前映像”,这个“前映像”用于以后的回滚、恢复和一致性读。(回滚段可以存储在专门的回滚表空间中,这个表空间由一个或多个物理文件组成,并专用于回滚表空间,回滚段也可在其它表空间中的数据文件中开辟)。
在修改信息写入数据文件时,其具体步骤如下:
1)改写db buffer块的数据内容,并在块的头部写入回滚段的地址。
2)将db buffer指针放入dirty list。如果一个行数据多次update而未commit,则在回滚段中将会有多个“前映像”,除了第一个“前映像”含有scn信息外,其他每个"前映像"的头部都有scn信息和"前前映像"回滚段地址。一个update只对应一个scn,然后服务器进程将在dirty list中建立一条指向此db buffer块的指针(方便dbwr进程可以找到dirty list的db buffer数据块并写入数据文件中)。接着服务器进程会从数据文件中继续读入第二个数据块,重复前一数据块的动作,数据块的读入、记日志、建立回滚段、修改数据块、放入dirty list。
3)当dirty queue的长度达到阀值(一般是25%),服务器进程将通知dbwr把脏数据写出,就是释放db buffer上的锁存器,腾出更多的free db buffer。前面一直都是在说明oracle一次读一个数据块,其实oracle可以一次读入多个数据块(db_file_multiblock_read_count来设置一次读入块的个数)
当执行commit时,具体步骤如下:
1)commit触发lgwr进程,但不强制dbwr立即释放所有相应db buffer块的锁。也就是说有可能虽然已经commit了,但在随后的一段时间内dbwr还在写这条sql语句所涉及的数据块。表头部的行锁并不在commit之后立即释放,而是要等dbwr进程完成之后才释放,这就可能会出现一个用户请求另一用户已经commit的资源不成功的现象。
2)从Commit和dbwr进程结束之间的时间很短,如果恰巧在commit之后,dbwr未结束之前断电,因为commit之后的数据已经属于数据文件的内容,但这部分文件没有完全写入到数据文件中。所以需要前滚。由于commit已经触发lgwr,这些所有未来得及写入数据文件的更改会在实例重启后,由smon进程根据重做日志文件来前滚,完成之前commit未完成的工作(即把更改写入数据文件)。
3)如果未commit就断电了,因为数据已经在db buffer更改了,没有commit,说明这部分数据不属于数据文件。由于dbwr之前触发lgwr也就是只要数据更改,(肯定要先有log)所有dbwr在数据文件上的修改都会被先一步记入重做日志文件,实例重启后,SMON进程再根据重做日志文件来回滚。
其实smon的前滚回滚是根据检查点来完成的,当一个全部检查点发生的时候,首先让LGWR进程将redologbuffer中的所有缓冲(包含未提交的重做信息)写入重做日志文件,然后让dbwr进程将dbbuffer已提交的缓冲写入数据文件(不强制写未提交的)。然后更新控制文件和数据文件头部的SCN,表明当前数据库是一致的,在相邻的两个检查点之间有很多事务,有提交和未提交的。
当执行rollback时,具体步骤如下:
服务器进程会根据数据文件块和db buffer中块的头部的事务列表和SCN以及回滚段地址找到回滚段中相应的修改前的副本,并且用这些原值来还原当前数据文件中已修改但未提交的改变。如果有多个”前映像“,服务器进程会在一个“前映像”的头部找到“前前映像”的回滚段地址,一直找到同一事务下的最早的一个“前映像”为止。一旦发出了commit,用户就不能rollback,这使得commit后dbwr进程还没有全部完成的后续动作得到了保障。
第五步:提取数据
当语句执行完成之后,查询到的数据还是在服务器进程中,还没有被传送到客户端的用户进程。所以,在服务器端的进程中,有一个专门负责数据提取的一段代码。他的作用就是把查询到的数据结果返回给用户端进程,从而完成整个查询动作。
从这整个查询处理过程中,我们在数据库开发或者应用软件开发过程中,需要注意以下几点:
一是要了解数据库缓存跟应用软件缓存是两码事情。数据库缓存只有在数据库服务器端才存在,在客户端是不存在的。只有如此,才能够保证数据库缓存中的内容跟数据库文件的内容一致。才能够根据相关的规则,防止数据脏读、错读的发生。而应用软件所涉及的数据缓存,由于跟数据库缓存不是一码事情,所以,应用软件的数据缓存虽然可以提高数据的查询效率,但是,却打破了数据一致性的要求,有时候会发生脏读、错读等情况的发生。所以,有时候,在应用软件上有专门一个功能,用来在必要的时候清除数据缓存。不过,这个数据缓存的清除,也只是清除本机上的数据缓存,或者说,只是清除这个应用程序的数据缓存,而不会清除数据库的数据缓存。
二是绝大部分SQL语句都是按照这个处理过程处理的。我们DBA或者基于Oracle数据库的开发人员了解这些语句的处理过程,对于我们进行涉及到SQL语句的开发与调试,是非常有帮助的。有时候,掌握这些处理原则,可以减少我们排错的时间。特别要注意,数据库是把数据查询权限的审查放在语法语义的后面进行检查的。所以,有时会若光用数据库的权限控制原则,可能还不能满足应用软件权限控制的需要。此时,就需要应用软件的前台设置,实现权限管理的要求。而且,有时应用数据库的权限管理,也有点显得繁琐,会增加服务器处理的工作量。因此,对于记录、字段等的查询权限控制,大部分程序涉及人员喜欢在应用程序中实现,而不是在数据库上实现。
Oracle SQL语句执行顺序
(8)SELECT (9) DISTINCT (11) <select_list>
(1) FROM <left_table>
(3) <join_type> JOIN <right_table>
(2) ON <join_condition>
(4) WHERE <where_condition>
(5) GROUP BY <group_by_list>
(6) WITH {CUBE | ROLLUP}
(7) HAVING <having_condition>
(10) ORDER BY <order_by_list>
1)FROM:对FROM子句中的表执行笛卡尔积(交叉联接),生成虚拟表VT1。
2)ON:对VT1应用ON筛选器,只有那些使为真才被插入到TV2。
3)OUTER (JOIN):如果指定了OUTER JOIN(相对于CROSS JOIN或INNER JOIN),保留表中未找到匹配的行将作为外部行添加到VT2,生成TV3。如果FROM子句包含两个以上的表,则对上一个联接生成的结果表和下一个表重复执行步骤1到步骤3,直到处理完所有的表位置。
4)WHERE:对TV3应用WHERE筛选器,只有使为true的行才插入TV4。
5)GROUP BY:按GROUP BY子句中的列列表对TV4中的行进行分组,生成TV5。
6)CUTE|ROLLUP:把超组插入VT5,生成VT6。
7)HAVING:对VT6应用HAVING筛选器,只有使为true的组插入到VT7。
8)SELECT:处理SELECT列表,产生VT8。
9)DISTINCT:将重复的行从VT8中删除,产品VT9。
10)ORDER BY:将VT9中的行按ORDER BY子句中的列列表顺序,生成一个游标(VC10),生成表TV11,并返回给调用者。
以上每个步骤都会产生一个虚拟表,该虚拟表被用作下一个步骤的输入。这些虚拟表对调用者(客户端应用程序或者外部查询)不可用。只有最后一步生成的表才会会给调用者。如果没有在查询中指定某一个子句,将跳过相应的步骤。

‘拾’ 如何用SQL分析电商用户行为数据(案例)

        

本文以“淘宝用户行为数据集”的分析全过程为例,展示数据分析的全过程

——使用工具:MySQL,Excel,Navicat,PowerBI

——分析类型:描述分析,诊断分析

——分析方法:漏斗分析,用户路径分析,RFM用户价值分析,活跃/存留分析,帕累托分析,假设验证分析。

(考虑到阅读体验文章中只放了SQL截图,如需PDF版本,再公众号后台回复“用户行为分析”领取)

(目录如下)

       

1.分析流程和方法

当没有清晰的数据看板时我们需要先清洗杂乱的数据,基于分析模型做可视化,搭建描述性的数据看板。

然后基于描述性的数据挖掘问题,提出假设做优化,或者基于用户特征数据进行预测分析找规律,基于规律设计策略。简单来说:

——描述性分析就是:“画地图”

——诊断性分析就是:“找问题”

——预测性分析就是 :“找规律”


在数据分析中有两个典型的场景:

一种是有数据,没有问题:需要先整体分析数据,然后再根据初步的描述分析,挖掘问题做诊断性分析,提出假设,设计策略解决问题。

 

另一种是已经发现了问题,或者已经有了假设,这种做数据分析更偏向于验证假设。

 

2.淘宝用户行为分析

本次是对“淘宝用户行为数据集”进行分析,在分析之前我们并不知道有什么问题,所以需要先进行描述性分析,分析数据挖掘问题。

我们首先来看下这个数据集的元数据:

       

根据以上数据字段我们可以拿用户行为为主轴从纵深方向提出一些问题,然后再从数据中找答案

       

纵向:

——这个数据集中用户的日活跃和周活跃时间有什么规律吗?

——在当日活跃的用户次日,三日,四日……还有多少活跃?

深向:

——用户从浏览到购买的整体转化率怎么样?

——用户从浏览到购买的路径是怎么样子的? 

——平台主要会给用户推送什么商品?

——用户喜欢什么类目?喜欢什么商品? 

——怎么判断哪些是高价值用户 ? 

 

 

下面是叮当整理的常用分析方法:      

我们可以给前面的问题匹配一下分析方法,便于后面的分析:


为了便于后面的数据分析,在分析之前我们需要先对做一下清洗

看元数据(字段解释,数据来源,数据类型,数据量……)初步发现问题为之后的处理做准备。

       

确定缺失值范围,去除不需要字段,填充缺失内容    

根据元数据格式和后续分析需要的格式对数据进行处理

  


去除重复值,异常值

——去除重复值:并把用户ID,商品ID,时间戳设置为主键

——异常值处理:查询并删除2017年11月25日至2017年12月3日之外的数据

     

查询并删除小于2017-11-25的

——验证数据:      


——分析思路:

——SQL提数:

       

       

——Excel可视化:

       

活跃曲线整体为上升状态,同为周六日,12月2号,3号相比11月25日,26日活跃度更高。

用户在周六周日相比其他时间更活跃(周六周日为休息日,用户有更多时间)

      

一天内用户活跃的最高峰期为21点(用户在这个时间段空闲较多)

 

——分析思路:

——SQL提数:

列出每用户每天及当天后面又活跃的日期,并创建“活跃时间间隔表”用于后面求次日存留,三日存留……

       

对“活跃时间间隔表视图”引用进行分组统计,计算每日存留人数并创建视图

对存留人数表进行计算,统计活跃用户留存率

——Excel可视化:

       

——分析思路:

——SQL提数:

-把各种用户行为分离出来并创建视图方便后续查询用户行为数据

查询整体数据漏斗

——Excel可视化:

       

用户从浏览到购买整体转化率2.3%,具体主要在哪个环节流失还需要再细分用户路径分析

 

——分析思路:

       

——SQL提数:

——PowerBI可视化:

       

用户从浏览到购买的路径主要有4条,路径越长转化率越底

路径1:浏览→购买:转化率1.45%

路径2:浏览→加购物车→购买:转化率0.33

路径3:浏览→收藏→购买:转化率0.11%

路径4:浏览→收藏→加购物车→购买:转化率0.03%

——分析思路:

——SQL提数:


——Excel可视化:

       

——描述性分析:

浏览量top100的商品浏览量呈阶梯分布,越靠前的阶梯之间的落差相对越大在这个阶梯中的商品越少,越靠后商品浏览量阶梯之间的落差相对越小,同阶梯内的商品越多。

浏览量TOP100的商品所属类目中,4756105,3607361,4357323三个类目浏览量远超其他类目。

——分析思路:

——SQL提数:

查询计算商品转化率,升序排列,取前100个

       

——Excel可视化:

       

——描述性分析:

从商品看:有17款商品转化率超过了1。

从类目看:这些商品所属类目分布均匀,除965809,4801426,2735466,2640118,5063620,4789432,2945933这7个类目之外,其他类目都只有一个商品在转化率TOP100的商品中。

——分析思路:

用户价值分析常用的分析方式是RFM模型

       

本次分析中的R,F,M具体定义(仅用于演示分析方法,无实际业务参考价值):

 

——SQL取数与分析:

1)建立打分标准:先计算R,F的值,并排序,根据R,F值最大值和最小值得区间设计本次得打分标准

-查询并计算R,F值创建视图

       

-引用RF数值表,分别查询R,F的最大值和最小值

       

       

-结合人工浏览的建立打分标准      

2)给R,F按价值打分

3)计算价值的平均值

       

4)用平均值和用户分类规则表比较得出用户分类   

     

——Excel可视化      

 

通过描述性分析得到可视化的数据后我们一般会先看一下是否符合业务常识

如果符合常识接下来我们会通过与行业平均数据和本产品的同比环比对比看是否正常,如果不正常就要找原因,设计解决方案,如果正常那就看是否有可以优化的地方。

       

我们首先来看一下这些描述性分析是否符合业务常识和指标是否正常:

       

1.活跃曲线整体为上升状态,同为周六日,12月2号,3号相比11月25日,26日活跃度更高。

2.用户在周六周日相比其他时间更活跃

3.一天内用户活跃的最高峰期为21点

4.从2017年11月15日致2017年12月3日,活跃用户新增38%

5.从2017年11月15日致2017年12月3日,活跃用户次日留存增长18.67%,当日的活跃用户留存也在快速增长,第七日留存比次日留存高18.56%。

6.用户从浏览到购买整体转化率2.3%

7.用户从浏览到购买的路径主要有4条,路径越长转化率越低。

8.浏览量top100的商品浏览量呈阶梯分布,越靠前的阶梯之间的落差相对越大在这个阶梯中的商品越少,越靠后商品浏览量阶梯之间的落差相对越小,同阶梯内的商品越多。

9.浏览量TOP100的商品所属类目中,4756105,3607361,4357323三个类目浏览量远超其他类目。

10.从商品看:有17款商品转化率超过了1。

11.从类目看:这些商品所属类目分布均匀,除965809,4801426,2735466,2640118,5063620,4789432,2945933这7个类目之外,其他类目都只有一个商品在转化率TOP100的商品中。

根据以上诊断分析我们梳理出了以下假设,做假设验证。

       

 

假设1:这些商品中有高转化率的爆款商品

       

 

对比浏览量TOP5的商品,发现这些商品转化率在同一类目下并不高,假设不成立

 

假设2:4756105,3607361,4357323三个类目属于高频刚需类目

-创建类目购买频次表

       

-计算类目购买频次平均值

       

-查询4756105,3607361,4357323三个类目的购买频次       

4756105,3607361,4357323三个类目的用户购买频次明显高于平均值,假设成立

 

假设3:有部分用户是未点击商详直接从收藏和购物车购买的。

       

用户不是直接从收藏和购物车购买的,只是后续复购未点击商详,假设不成立

 

假设4:淘宝推荐的商品主要是“同一类目下的高转化商品”

       

用Excel对浏览量TOP100的商品ID和转化率TOP100的商品ID进行去重,结果无重复值,假设不成立


3.结论:

1)用户活跃:用户活跃曲线整体呈上升趋势,在一周中周六,周日活跃度比平时更高,在一天中用户活跃曲线从凌晨4点开始往上升,在中午12点和下午5~6点有两个小低谷(吃饭),到晚上9点时活跃度达到顶峰。

 

2)用户留存:从2017年11月15日致2017年12月3日的用户留存数据来看,淘宝的用户留存数据较好,活跃用户次日留存增长18.67%,当日的活跃用户留存也在快速增长,第七日留存比次日留存高18.56%。

 

3)用户转化:整体转化2.3%,用户从浏览到购买的路径主要有4条,路径越长转化率越低。

4)平台推荐与用户偏好:从数据集中的数据来看,排除用户兴趣偏好标签,淘宝给用户用户推送的商品主要是高频刚需的类目,促使用户复购,流量回流平台。

 

以上结论受数据量和数据类型的影响,并不一定准确,仅用来练习数据分析方法。

(考虑到阅读体验文章中只放了SQL截图,如需PDF版本,再公众号后台回复“用户行为分析”领取)