SQL,发音为“sequel”(或SQL,如果愿意的话),是数据科学家的重要工具。实际上,它可以说是获取数据工作中最重要的语言。在共享单车数据分析的SQL设计中,我们将从入门者的角度深入研究SQL基础知识,以使您入门并掌握这一关键技能。
让我们从回答一个简单的问题开始:
什么是SQL?
SQL代表结构化查询语言。查询语言是一种编程语言,旨在促进从数据库中检索特定信息,而这正是SQL所做的。简而言之,SQL是数据库的语言。
这很重要,因为大多数公司将其数据存储在数据库中。尽管数据库类型很多(例如MySQL,PostgreSQL,MicrosoftSQLServer),但是大多数数据库都使用SQL,因此一旦掌握了SQL基础知识,便可以使用其中的任何一个。
即使您打算使用Python之类的另一种语言进行分析,在大多数公司中,您仍可能需要使用SQL从公司的数据库中检索所需的数据。在撰写共享单车数据分析的SQL设计时,仅在美国,Indeed上就列出了80,多个SQL作业。
因此,让我们开始学习SQL!
(如果您希望通过浏览器进行交互学习,编写和运行SQL查询,则应查看我们的SQL基础课程,该课程免费)
为了避免广告的嫌疑,我们选择国外的一个共享单车来举例子,在共享单车数据分析的SQL设计中,我们将使用自行车共享服务Hubway的数据集,其中包括使用该服务进行的超过万次旅行的数据。
在开始用SQL编写我们自己的一些查询之前,我们将首先看一下数据库,它们是什么以及为什么使用它们。
如果您想继续,可以在这里下载hubway.db文件(MB)。
SQL基础:关系数据库
关系数据库是一种数据库,该数据库存储跨多个表的相关信息,并允许您同时查询多个表中的信息。
通过思考一个例子,更容易理解它是如何工作的。假设您是一家企业,并且想要跟踪销售信息。您可以在Excel中设置一个电子表格,在其中您要跟踪的所有信息都以单独的列显示:订单号,日期,到期金额,装运跟踪号,客户名,客户地址和客户电话号码。
此设置可以很好地跟踪所需的信息,但是当您开始从同一位客户那里获得重复订单时,您会发现他们的姓名,地址和电话号码存储在电子表格的多行中。
随着业务的增长和要跟踪的订单数量的增加,这些冗余数据将占用不必要的空间,并通常会降低销售跟踪系统的效率。您可能还会遇到数据完整性问题。例如,不能保证每个字段都将填充正确的数据类型,或者每次都以完全相同的方式输入名称和地址。
与上图中的关系数据库一样,使用关系数据库可以避免所有这些问题。您可以设置两个表,一个用于订单,一个用于客户。“客户”表将包括每个客户的唯一ID号,以及我们已经跟踪的姓名,地址和电话号码。“订单”表将包括您的订单号,日期,应付金额,跟踪号,并且在每个客户数据项中没有一个单独的字段,而是一个客户ID列。
这使我们能够提取任何给定订单的所有客户信息,但是我们只需要在数据库中存储一次即可,而不必为每个订单再次列出它。
我们的数据集
让我们开始看看我们的数据库。该数据库有两个表,trips和stations。首先,我们只看trips表。它包含以下列:
1)id—用作每次旅行的参考的唯一整数
2)duration—行程时间,以秒为单位
3)start_date—旅行开始的日期和时间
4)start_station—一个整数,与该行开始于的车站的表中的id列相对应stations
5)end_date—旅行结束的日期和时间
6)end_station—行程终点站的“id”
7)bike_number—旅途中所用自行车的Hubway唯一标识符
8)sub_type—用户的订阅类型。Registered对于具有成员资格Casual的用户,对于没有成员资格的用户
9)zip_code—用户的邮政编码(仅适用于注册会员)
10)birth_date—用户的出生年份(仅适用于注册会员)
11)gender—用户的性别(仅适用于注册会员)
我们的分析
有了这些信息和我们将很快学习的SQL命令,以下是我们在共享单车数据分析的SQL设计中将尝试回答的一些问题:
1)最长旅行的持续时间是多少?
2)“注册”用户进行了多少次旅行?
3)平均旅行时间是多少?
4)注册用户或临时用户旅行更长吗?
5)大多数旅行中使用哪辆自行车?
6)30岁以上的用户平均旅行时间是多少?
我们将用来回答这些问题的SQL命令是:
1)SELECT
2)WHERE
3)LIMIT
4)ORDERBY
5)GROUPBY
6)AND
7)OR
8)MIN
9)MAX
10)AVG
11)SUM
12)COUNT
安装与设定
就共享单车数据分析的SQL设计而言,我们将使用一个名为SQLite3的数据库系统。从2.5版开始,SQLite已经成为Python的一部分,因此,如果您安装了Python,则几乎肯定也会安装SQLite。如果尚未安装Python和SQLite3库,则可以使用Anaconda轻松进行安装和设置。
使用Python运行我们的SQL代码可以使我们将结果导入到Pandas数据框中,从而更易于以易于阅读的格式显示结果。这也意味着我们可以对从数据库中提取的数据进行进一步的分析和可视化,尽管这超出了共享单车数据分析的SQL设计的范围。
另外,如果我们不想使用或安装Python,则可以从命令行运行SQLite3。只需从SQLite3网页下载“预编译的二进制文件”,然后使用以下代码打开数据库:
在这里,我们只需键入要运行的查询,我们将在终端窗口中看到返回的数据。
使用终端的另一种方法是通过Python连接到SQLite数据库。这将使我们能够使用Jupyter笔记本,以便我们可以在格式整齐的表中查看查询的结果。
为此,我们将定义一个函数,该函数将查询(存储为字符串)作为输入并将结果显示为格式化的数据框:
当然,我们不必在SQL中使用Python。如果您已经是R程序员,那么我们的R用户SQL基础知识课程将是一个不错的起点。
选择
我们将使用的第一个命令是SELECT。SELECT将几乎是我们编写的每个查询的基础-它告诉数据库我们要查看哪些列。我们既可以按名称指定列(用逗号分隔),也可以使用通配符*返回表中的每一列。
除了要检索的列之外,我们还必须告诉数据库从哪个表获取它们。为此,我们使用关键字,FROM后跟表名。例如,如果我们想看到的start_date,并bike_number在每行trips表中,我们可以使用下面的查询:
在此示例中,我们从SELECT命令开始,以便数据库知道我们希望它为我们找到一些数据。然后,我们告诉数据库我们对start_date和bike_number列感兴趣。最后,我们过去FROM使数据库知道我们要查看的列是trips表的一部分。
编写SQL查询时要意识到的重要一件事是,我们希望每个查询都以分号(;)结尾。并非每个SQL数据库实际上都需要这样做,但是有些确实需要,所以最好养成这种习惯。
限制
开始在Hubway数据库上运行查询之前,我们需要知道的下一个命令是LIMIT。LIMIT只是告诉数据库您希望它返回多少行。
SELECT我们在上一节中查看的查询将为表中的每一行返回所请求的信息trips,但是有时这可能意味着大量数据。我们可能不想要所有这些。相反,如果我们想看到的start_date,并bike_number在数据库中的第一个五年的旅行,我们可以添加LIMIT到我们的查询,如下所示:
我们仅添加了LIMIT命令,然后添加了一个数字,该数字表示我们要返回的行数。在本例中,我们使用5,但您可以将其替换为任何数字,以获取正在处理的项目的适当数据量。
LIMIT在共享单车数据分析的SQL设计中,我们将在Hubway数据库中的查询中使用很多–该trips表包含超过万行数据,我们当然不需要显示所有数据!
让我们在Hubway数据库上运行第一个查询。首先,我们将查询存储为字符串,然后使用我们先前定义的函数在数据库上运行它。看下面的例子:
该查询*用作通配符,而不是指定要返回的列。这意味着该SELECT命令已为我们提供了trips表中的每一列。我们还使用该LIMIT函数将输出限制为表的前五行。
您会经常看到人们在查询中使用大写的逗号(这是我们在共享单车数据分析的SQL设计中将遵循的约定),但这主要是优先考虑的问题。大写字母使代码更易于阅读,但实际上丝毫不影响代码的功能。如果您希望使用小写命令编写查询,则查询仍将正确执行。
我们前面的示例返回trips表中的每一列。如果只对duration和start_date列感兴趣,则可以按如下所示用列名替换通配符:
订购
在回答第一个问题之前,我们需要知道的最终命令是ORDERBY。此命令使我们可以对给定列上的数据库进行排序。
要使用它,我们只需指定要排序的列的名称。默认情况下,ORDERBY按升序排序。如果我们想指定数据库应该排序的顺序,我们可以添加关键字ASC以升序或DESC降序。
例如,如果我们想将trips表从最短duration到最长排序,我们可以在查询中添加以下行:
有了SELECT,LIMIT和ORDERBY命令之后,我们现在可以尝试回答第一个问题:最长旅行的持续时间是多少?
要回答这个问题,将其分为几个部分并确定我们需要解决每个部分的命令会很有帮助。
首先,我们需要从表的duration列中提取信息trips。然后,要找出最长的行程,我们可以duration按降序对列进行排序。我们可能会通过以下方式提出一个查询,该查询将获取我们正在寻找的信息:
1)使用SELECT检索duration列FROM的trips表
2)使用ORDERBY排序的duration列,并使用DESC关键字来指定要在降序排序
3)用于LIMIT将输出限制为1行
以这种方式使用这些命令将返回持续时间最长的单行,这将为我们提供问题的答案。
需要注意的另一件事-随着查询添加更多命令并变得更加复杂,如果将它们分成多行,您可能会更容易阅读。就像大写一样,这是个人喜好问题。它不会影响代码的运行方式(系统只是从头开始读取代码,直到到达分号为止),但它可以使您的查询更清晰,更易于理解。在Python中,我们可以使用三引号将字符串分隔为多行。
让我们继续运行此查询,找出最长的旅程持续了多长时间。
现在我们知道最长的旅程持续了秒,或者说是分钟多一点。但是,最大值为时,我们不知道这是否真的是最长行程的长度,或者数据库是否仅设置为允许四位数的数字。
如果确实由数据库缩短了特别长的行程,那么我们可能期望在秒处看到很多行程,它们达到了极限。让我们尝试运行与之前相同的查询,但是将调整LIMIT为返回10个最长持续时间,以查看是否为这种情况:
我们在这里看到的是,在年并没有一整趟旅行,因此看起来我们并没有切断持续时间的高端,但是仍然很难判断这是否是真正的行程跳闸或最大允许值。
Hubway会为30分钟以上的骑行收取额外费用(某人保持秒的自行车将不得不支付25美元的额外费用),因此他们认为4位数字足以追踪大多数骑行是合理的。
哪里
前面的命令非常适合提取特定列的排序信息,但是如果我们要查看数据的特定子集,该怎么办?就是这样WHERE。WHERE命令允许我们使用逻辑运算符指定应返回的行。例如,您可以使用以下命令返回bike的每次旅行B:
您还会注意到,我们在此查询中使用引号。那是因为bike_number储存为字串。如果该列包含数字数据类型,则不需要引号。
让我们编写一个查询,该查询WHERE用于返回trips表中每一行的每一列,这些查询的duration时间超过秒:
如我们所见,此查询返回了14个不同的行程,每个行程持续秒或更长。关于此查询的突出之处是,除一个结果外,所有结果都具有sub_type的Casual。也许这表明Registered用户更了解长途旅行的额外费用。也许Hubway可以更好地向休闲用户传达其价格结构,以帮助他们避免超额收费。
我们已经知道,即使是SQL的初学者级命令也可以如何帮助我们回答业务问题并在数据中寻找见解。
返回到WHERE,我们也可以WHERE使用AND或在子句中组合多个逻辑测试OR。例如,如果在我们之前的查询中,共享单车数据分析的SQL数据库设计