通俗易懂的方式教你写SQL查询语句

SQL作为一门结构化查询语句,能实现增删查改的功能。通常为了保证数据安全,增删改都设有管理员权限;查询语句不改变原始数据,查询语句是最常用的语句。本文介绍SQL查询语句的基本内容。

话不多说,先上套路:

Select 列名 (as 别名)

From 表名 (as 别名)

(where 条件)

(Union/ Union All)

(Group By 列名)

(Having 条件)

(Order By 列名)

Select是查询语句的关键字,指示数据库进行查询操作。SQL查询语句关键字顺序按照上述顺序排列,Select在最前,From指明被查询数据表,这两个是必选关键字;从where开始带括号部分是可选关键字:其中Union用作联合多个Select查询;Group By的作用是按照指定列分组显示查询结果;Having也是筛选数据的作用,后文再详解;Order By起到排序显示查询结果的作用。

为了讲述的更加直观,本文用以下表结构图说明:

图一 外卖数据库表结构图

附:图来自百度,侵删。

表结构关系图中展示了数据库中的7张表。除Evaluate表和Oderstatem表外,其余五张表都有自己唯一独立的ID(主键);同时所有表之间也有外键相互关联。例如Food表有独立ID作为自己的主键,同时有Userid(User表的主键)与User表关联;Food表的ID还是Evaluate表和Oderstatem表的外键。数据库允许多字段组合成唯一标识的主键,Evaluate表和Oderstatem表可以组合各自的两个外键作为自己的主键。

不论是什么样的查询,第一步工作是需要了解表间关系,只有表间关系清晰无误的情况下,才能实现有效的查询。本文以上图为例,讲解SQL查询的基本方法。

一、单个表查询

(1)普通单表查询

例如从User表选择ID为666,999的用户的全部信息,并且按照用户的Name排序,则需要以下语句:

Select *

From User

Where ID IN ('666','999')

-- 等价于 where ID = '666' OR ID = '999'

Order By Name;

"*"表示需要选择表中的全部列信息;关键字IN指明了查询筛选条件,只选取666和999编号的用户。

Order By是排序关键字,所有查询语句中,Order By放在查询语句最末尾。上面的语句有两个筛选条件,使用OR或IN关键字链接能起到相同的效果。

(2)需要自联接的单表查询

自连接查询其实可以看做是多表查询,只是使用到的是两张万全一样的表。某些特殊情况需要使用到这种查询方式。例如:

出于某种需求,要统计点了相同菜品的不同用户的ID及菜品信息,则需要自联接实现:

Select f1.Userid, f1.Name

From Food AS f1, Food AS f2 --AS关键字可以省略,Oracle无AS关键字

Where f1.Name = f2.Name AND f1.Userid f2.Userid

Group By f1.Name;

上面的查询语句用到了自联接,为了防止歧义,对两个表分别取了f1,f2别称,并用f1.Userid和f2.Name等明确指明了查询表。查询逻辑是先找到f1、f2两张表菜品相同的记录,此时同一用户的订单会被筛选出来,为了防止同一用户ID的订单被选出,增加两个表ID不等的过滤条件,最终获得想要的数据。最后以Group By结束,保证查询结果按照菜品分组显示。

二、多表查询

多表查询需要表与表之间有关联关系,即至少有一列内容是两个表都有存在的,否则查询将不会返回有效数据。多表联接分为Inner Join(同Join)、Left Outer Join(同Left Join)、Right Outer Join(同Right Join)和Full Outer Join(极少使用)四种。第一种联接为内连接,只有两个表筛选条件列完全相等时,才能被筛选出来;第二种为左外联接,筛选结果以Left关键字左侧表为基础,如 a Left Join b on a.id = b.id,则以a表为基础,b表id与a表id相等的数据能被筛选出来,b表无id与a表id相等,则a表对应位置将显示为NULL。第三种为右联接,以Right关键字右侧表为基础,情况正好与Left Join的例子相反。

以上介绍的Left Join和Right Join的唯一区别是关联的表的顺序,二者可以相互转换;Inner Join一般可以用更简单的where条件替代。在具体使用时,应该选择更简便的代码实现。

(1)两表联接

现需要分析点了“狮子头”类外卖,且对应菜品单大于10的所有用户的ID,Name,Address信息及菜品单价(假设Food表的Outcount列为菜品数量)。由表结构图,已知用户信息存储在User表,而订单菜品信息存储在Food表,两个表通过User表的主键关联。

方法一:用Inner Join实现

Select U.ID, U.Name, U.Address, F.Name,

(F.Price/F.Outcount) AS Uprice

From User AS U Inner Join Food AS F

ON U.ID = F.Userid

Where F.Name LIKE '%狮子头%'

Group by F.Name

Having Uprice > 10;

方法二:使用where条件联接表

Select U.ID, U.Name, U.Address, F.Name, (F.Price/F.Outcount) AS Uprice

From User AS U , Food AS F

Where U.ID = F.Userid and F.Name LIKE '%狮子头%'

Group By F.Name

Having Uprice > 10;

方法一、二实现了同样的效果,同时还使用到了新的关键字:Like,Having。个人认为方法二更为直观和简单。Like关键字主要用于通配条条件,mysql通配符%表示通配任意长度字符。

Having和Where实现的功能基本一样,都是过滤数据的条件。其区别在于Where用了过滤行级数据;Having一般固定跟在Group By后面,过滤分组数据,语法与where类似。

(2)三个及以上表查询

三表查询查询与两表查询逻辑一致,需要首先找到表与表之间的关联关系,然后联接各表,最后查询所需数据。三表查询一般会涉及一些聚集函数,也可以很轻松实现,如sum,avg,count,min,max等。

统计每个用户的外卖订单量、外卖菜品总数、外卖总消费数据、区域分布状况。该查询需要用到User表、Food表和OrderStatem表。User表与Food表关联,Food表与OrderStatem表关联。最终需要选取的数据在User表和OrderStatem表中,Food表主要起到了“牵线搭桥”的过渡作用。查询语句如下:

Select U.ID, U.Name, U.Address ,Count(*),

SUM(O.FoodCount) AS TFN ,SUM( O.FoodTotalPrice) AS TFP

From OrderStatem O Left Join Food F

ON O.FoodID = F.ID Left Join User U

ON U.ID = F.Userid

Group By U.ID, U.Address

Order By TFN, TFP

以上查询语句中,通过中间表实现了多表查询功能。用到了三个表Left Join的方法,用Right Join可以实现完全一样的功能。这两种方法的好处是可以统计注册了外卖账号,但是没有在平台点过外卖的客户的信息。

如果只需要拉取下过订单的客户的数据,可以采用Inner Join或ID相等的Where语句筛选的方法实现:

Select U.ID, U.Name, Count(*),

SUM(O.FoodCount) AS TFN ,SUM( O.FoodTotalPrice) AS TFP

From OrderStatem O, Food F, User U

Where O.FoodID = F.ID AND U.ID = F.Userid

Group By U.ID, U.Address

Order By TFN, TFP

以上例子展示了三个表联结查询的方法,多表查询可以参考以上例子,操作大同小异。

另外需要特别注意的是,在多表查询过程中,一定要通过Where语句指定行筛选条件,或者用Join方法指定联结条件,然后在进行查询,否则会出现笛卡儿积现象,一个表的任一行都关联了另一个表的所有行,不仅降低效率,而且查询出的数据也无效。

以上例子说明了SQL查询时最基本的语法,可以帮助实现最基本的查询操作。另外例子中涉及了一些SQL聚集函数、通配查询方法等。后续继续讲解具体用法。由于不同操作平台上SQL语法、部分函数用法会存在差异,功能实现也许存在差异。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180926G0HSIP00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券