《SQL必知必会》学习笔记(二)

第7课 创建计算字段
存储在数据库中的数据一般不是应用程序所需要的格式,我们需要直接从数据库中检索出转换、计算或格式化的数据,而不只是检索出数据,然后再去客户端应用程序中重新格式化。计算字段并不实际存在于数据库表中,计算字段时运行时再select语句内创建的。
字段(field)基本上于列(column) 的意思相同,经常互换使用,不过数据库列一般称为列,而字段这个属于通常在计算字段这种场合下使用。
一、拼接字段
拼接(concatenate)将值联结在一起(将一个值附加到另一个值)构成单个值。
1、案例介绍,vendors表中包含供应商名和地址信息,假如要生成一个供应商报表,需要在格式化的名称(位置)中列出供应商的位置。此报表需要一个值,而表中数据存储在两个列vend _name和vend_country中,此外,需要用括号vend_country括起来,这些东西都没有存储在数据库表中。可使用操作符(+)或两个竖杠(||)表示。
输入:select vend_name + '(' + vend_country + ')' from vendors order by vend_name;
输入:select vend_name || '(' || vend_country || ')' from vendors order by vend_name;
输入:select contact(vend_name , '(' ,vend_country,')') from vendors order by vend_name;
分析:上面的select语句拼接以下元素

  • 存储在vend_name列中的名字
  • 包含一个空格和一个左圆括号的字符串
    -存储在vend_country列中的国家
  • 包含一个右圆括号的字符串
    语句返回的是结合成一个计算字段的两个列用空格填充,而实际上你要的结果不需要这些空格,可以使用rtrim()函数来完成,该函数用来去掉左右两边的所有空格,通过使用此函数,各个列都进行了整理。
    输入:select rtrim(vend_name) + '(' + rtrim(vend_country) + ')' from vendors order by vend_name;
    输入:select rtrim(vend_name) || '(' || rtrim(vend_country) || ')' from vendors order by vend_name;
    二、使用别名,有时也叫导出列(derived column)。新计算列的只是一个值,如果仅在sql查询工具中查看以下结果,这样没什么不好,但是,一个未命名的列不能用于客户端应用中,因为客户端没有办法引用它。别名(alias)是一个字段或值的替换名。别名用as关键字赋予。
    输入:select rtrim(vend_name) + '(' + rtrim(vend_country) + ')' as vend_title from vendors order by vend_name;
    输入:select rtrim(vend_name) || '(' || rtrim(vend_country) || ')' as vend_title from vendors order by vend_name;
    输入:select contact(vend_name , '(' ,vend_country,')') as vend_title from vendors order by vend_name;
    as指定计算结果的名为vend_title,任何客户端应用都可以按名称引用这个列,就像它是一个实际的表列一样。as也可用于在实际的表列名包含不合法的字符(如空格)时重新命名它,在原来的名字含混或容易误解时扩充它。
    三、执行算术计算
    计算字段的另一个常见用途是对检索出的数据进行算数计算。
    案例:orders表包含收到的所有订单,orderitems表包含每个订单中的各项物品。下面的sql语句检索订单号20008中的所有物品。
    输入:select prod_id, quantity, item_price from orderitems where order_num = 20008;
    输入:select prod_id, quantity, item_price, quantityitem_price as expanded_price from orderitems where order_num = 20008;
    输出中显示expanded_price 列是一个计算字段,此计算为quantity
    item_price。客户端应用现在可以使用这个新计算列,就像使用其它列一样。sql支持的算数操作符包括+-*/,圆括号可以用来区分优先顺序
    如何测算数据?select语句为测试、检验函数和计算提供了很好的方法,但是省略了from子句后就是简单地访问和处理表达式。

第8课 使用函数处理数据
与大多数计算机语言一样,sql也可以用函数来处理数据,函数一般是再数据上执行的,为数据的转换和处理提供方便。几乎所有的DBMS都同等地支持sql语句,单但每一个dbms都有特定的函数,每个函数的名称和语法可能及其不同。
可移植(portable):所编写的代码可以在多个系统上运行。为了代码的可移植,许多sql程序员不赞成使用特定于实现的功能。如果你决定使用函数,应该保证做好代码注释,以便以后你自己(或他人)能确切地知道这些sql代码的含义。
一、文本处理函数(用于处理文本字符串,如删除或填充值,转换值为大写或小写)的文本函数
输入:select vend_name,upper(vend_name) as vend_name_upcase from vendors order by vend_name;
分析:upper()将文本转换成大写,因此本例中每个供应商都列出两次,第一次为vendors表中存储的值,第二次作为列vend_name_upcase转换为大些。
常用的文本处理函数
left()(或使用子字符串函数)。 返回字符串左边的字符
length()(也使用datalength()或len())返回字符串的长度
lower() 将字符串转换为小写
ltrim() 去掉字符串左边的空格
right()(或使用字符串函数) 返回字符串右边的字符
rtrim() 去掉字符串右边的空格
substr() 或substring() 提取字符串的组成部分
soundex() 返回字符串的soundex值,是一个将任何文本串转换为描述其语音表示的字母数字模式的算法。考虑了类似的发音音符和音节,使得能对字符串进行发音比较而不是字母比较
输入:select cust_name,cust_contact from customers where soundex(cust_contact)=soundex('Michael green');(他匹配到所有发音类似于Michael green)
二、日期或事件处理函数
输入:select order_num from orders where datepart(yy,order_date)=2020;
datepart()函数,此函数返回日期的某一部分,有两个参数,它们分别是返回的成分和从中返回成分的日期。datepart()只从order_date列中返回年份,通过与2020比较,where子句只过滤此年份的订单。
输入:select order_num from orders where date_part('year',order_date)=2020;
输入:select order_num from orders where extract(year from order_date)=2020;
extract()函数用来提取日期成分,year 表示提取哪个部分,返回值再与2020进行比较
输入:select order_num from orders where order_date between to_date('2020-01-01','yyyy-mm-dd')and to_date('2020-12-31','yyyy-mm-dd')
输入:select order_num from orders where year(order_date)=2020;
输入:select order_num from orders where strftime('%y',order_date)='2020';
三、数值处理函数
abs() 返回一个数的绝对值
cos()返回一个角度的余弦
exp()返回一个数的指数值
pi()返回圆周率派的值
sin()返回一个角度的正弦
sqrt()返回一个数的平方根
tan()返回一个角度的正切

第9课 汇总数据
聚集函数(aggregate function),对某些行运行的函数,计算并返回一个值,用来汇总表的数据,我们经常汇总数据,而不用把它们实际检索出来。
1、AVG()函数,通过对表中行数计数并计算其列值之和,求得该列的平均值。可用来返回所有列的平均值,也可用来返回特定列或行的平均值。
输入:select avg(prod_price)as avg_price from products;(返回包含products表中所有产品的平均价格)
输入:select avg(prod_price)as avg_price from products where vend_id ='dll01';(where子句用来过滤除vend_id为dll01的产品,因此只返回该供应商产品的平均值),avg()函数忽略值为null的行
2、count()函数,用来确定表中行的数目或者符合特定条件的行的数目。首先,使用count()对表中行的数据进行计算,不管表列中包含的是空值(null)还是非空值;其次,使用count(column)对特定列中具有值的行进行计数,忽略null值。
输入:select count(
)as num_cust from customers;(利用count()对所有行计数,不管行中各列有什么值,计数值在num_cust中返回)
输入:select count(cust_email)as num_cust from customers;(使用count(cust_email)对cust_email列中有值的行进行计数)
针对null值,如果指定列名,则count()函数会忽略指定列的值为null的行,但如果count()函数中用的是星号(
),则不忽略
3、max()函数,返回指定列中的最大值,要求指定列名
输入:select max(prod_price)as max_price from products;(max()返回products表中最贵物品的价格)
注:一般用来找出最大的数值或日期值,但许多dbms允许将它返回任意列中的最大值,包括返回文本列中的最大值。在用于文本数据时,max()返回按该列排序的最后一行。忽略值为null的行
4、min()函数,返回指定列的最小值,与max()一样,min()要求指定列名
输入:select min(prod_price) as min_price from products;(返回products表中最便宜物品的价格,其余的注意事项与max类似)
5、sum()函数,返回指定列值的和(总计)。orderitems包含订单中实际的物品,每个物品都相应的数量。可如下检索所订物品的总数(所有quantity值之和)
输入:select sun(quantity) as items_ordered from orderitems where order_num =20005;(sum()返回订单中所有物品数量之和,where子句保证只统计某个物品订单中的物品)
输入:select sum(item_price*quantity) as total_price from orderitems where order_num =20005;(用来合计计算值,得出总的订单金额,where子句保证只统计某个物品订单中的物品)
sumI()函数忽略值为null的行。
二、聚集不同值
以上5个聚集函数都可以如下使用

  • 对所有行执行计算,指定all参数或不指定参数(因为all时默认行为)
  • 只包含不同的值,指定distinct参数
    提示:all为默认值,不需要指定。如果不指定distinct,则假定为all。
    输入:select avg(distinct prod_price)as avg_price from products where vend_id='dll01';(在使用distinct后,此例中的avg_price比较高,因为有多个物品具有相同的较低的价格。排除它们提升了平均价格)
    注意:distinct只能用于count()必须使用列名,不能用于计算或表达式,但不能用于count(
    三、组合聚集函数
    select语句可根据需要包含多个聚集函数
    输入:select count(
    ) as num_items,min(prod_price) as price_min, max(prod_price) as price_max,avg(prod_price) as price_avg from products;(这里用单挑select语句执行了4个聚集计算,返回4个值)
    注意:取别名,在指定别名以包含某个聚集函数的结果时,不应该使用表中实际的列名。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352

推荐阅读更多精彩内容