您好,欢迎访问代理记账网站
移动应用 微信公众号 联系我们

咨询热线 -

电话 15988168888

联系客服
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

sql基础笔记

D:\”program files“\PostgreSQL\9.5\bin\psql.exe –U postgres

语句执行顺序(group by 比 select前)

groub by->select->order by

insert into a1 select * from a

使用group by 时select 后字段必须是在group by 后出现过的

(1)from
(3) join
(2) on
(4) where
(5)group by(开始使用select中的别名,后面的语句中都可以使用)
(6) avg,sum…
(7)having
(8) select
(9) distinct
(10) order by

表清空

truncate不能加where, group by, order by清空表比delete效率更高

从其它表中复制数据

INSERT INTO ProductCopy (product_id, product_name, product_type,
sale_price, purchase_price, regist_date)
SELECT product_id, product_name, product_type, sale_price,
purchase_price, regist_date
FROM Product;

新增列

alter table xxx add column newColum varchar not null;

事务开启与提交

begin transaction;

commit;

视图

表中保存的是实际数据

视图中保存的是select语句

1.create view actor_name_view (first_name_v,last_name_v) as
select first_name ,last_name from actor

2.create view actor_name_view as
select first_name first_name_v,last_name last_name_v from actor;

视图两大特点

1.无需保存数据,节省存储容量

2.将频繁使用的select语句保存成视图,不用重复书写,由于是执行select语句,视图中的数据随着表的内容变化

使用视图的查询

1.首先执行定义视图的select语句

2.根据得到的结果再执行from子句中使用视图的select语句

应该避免在视图上建立视图,多重视图会降低sql性能

视图和表需要同时进行更新,汇总的到的视图不能更新

子查询

– 在FROM子句中直接书写定义视图的SELECT语句
SELECT product_type, cnt_product FROM ( SELECT product_type, COUNT(*) AS cnt_product FROM Product GROUP BY product_type ) AS ProductSum;

先执行内层,再执行外层

标量子查询

标量子查询必须而且只能返回 1 行 1列的结果(不能返回多行结果),也就是返回表中某一行的某一列的值,例如“10”或者“东京都”这样的值。

标量子查询的返回值可以用在 = 或者 <> 这样需要单一值的比较运算符之中

SELECT product_id, product_name, sale_price
FROM Product
WHERE sale_price > (SELECT AVG(sale_price)
FROM Product);

无论是 SELECT 子句、GROUP BY 子句、HAVING 子句,还是ORDER BY 子句,几乎所有的地方都可以使用


SELECT product_id, product_name,
sale_price,
(SELECT AVG(sale_price)
FROM Product) AS avg_price
FROM Product;

执行结果
product_id | product_name | sale_price | avg_price
------------±----------------±----------±---------------------
0001 | T恤衫 | 1000 | 2097.5000000000000000
0002 | 打孔器 | 500 | 2097.5000000000000000
0003 | 运动T恤 | 4000 | 2097.5000000000000000
0004 | 菜刀 | 3000 | 2097.5000000000000000
0005 | 高压锅 | 6800 | 2097.5000000000000000
0006 | 叉子 | 500 | 2097.5000000000000000
0007 | 擦菜板 | 880 | 2097.5000000000000000
0008 | 圆珠笔 | 100 | 2097.5000000000000000

关联子查询

SELECT product_type, product_name, sale_price FROM Product AS P1 WHERE sale_price > (SELECT AVG(sale_price) FROM Product AS P2 WHERE P1.product_type = P2.product_type GROUP BY product_type);


分组计算平均数

select product_id,product_name,product_type,sale_price,(
select avg(sale_price)
from Product as p2
where p1.product_type = p2.product_type
group by p1.product_type
) as avg_sale_price
from Product as p1;

±-----------±-------------±-------------±-----------±---------------+
| product_id | product_name | product_type | sale_price | avg_sale_price |
±-----------±-------------±-------------±-----------±---------------+
| 001 | TT血衫 | 衣服 | 1000 | 2500.0000 |
| 002 | 打孔器 | 办公用品 | 500 | 300.0000 |
| 003 | 运动T血 | 衣服 | 4000 | 2500.0000 |
| 004 | 菜刀 | 厨房用具 | 3000 | 2795.0000 |
| 005 | 高压锅 | 厨房用具 | 6800 | 2795.0000 |
| 006 | 叉子 | 厨房用具 | 500 | 2795.0000 |
| 007 | 擦菜板 | 厨房用具 | 880 | 2795.0000 |
| 008 | 圆珠笔 | 办公用品 | 100 | 300.0000 |
±-----------±-------------±-------------±-----------±---------------+

函数

数值

ABS(数值)

MOD(被除数,除数) a%b

ROUND(对象数值,保留小数的位数)

字符串

**拼接:**字符串1||字符串2

concat(s1,s2)

SELECT str1, str2, str3,
CONCAT(str1, str2, str3) AS str_concat
FROM SampleStr;

**长度:**LENGTH(字符串)

LOWER(字符串)

UPPER(字符串)

REPLACE(对象字符串,替换前的字符串,替换后的字符串)

截取:

SUBSTRING(对象字符串 FROM 截取的起始位置 FOR 截取的字符数)

SUBSTR(str1, 3, 2)

日期函数

当前日期: SELECT CURRENT_DATE;

当前时间: SELECT CURRENT_TIME;

日期和时间: SELECT CURRENT_TIMESTAMP;

日期截取:

SELECT CURRENT_TIMESTAMP,
EXTRACT(YEAR FROM CURRENT_TIMESTAMP) AS year,
EXTRACT(MONTH FROM CURRENT_TIMESTAMP) AS month,
EXTRACT(DAY FROM CURRENT_TIMESTAMP) AS day,
EXTRACT(HOUR FROM CURRENT_TIMESTAMP) AS hour,
EXTRACT(MINUTE FROM CURRENT_TIMESTAMP) AS minute,
EXTRACT(SECOND FROM CURRENT_TIMESTAMP) AS second;

执行结果:

now | year | month | day | hour | minute | second
---------------------------------±-----±------±----±----±-------±------
2010-04-25 19:07:33.987+09 | 2010 | 4 | 25 | 19 | 7 | 33.987

类型转化cast

CAST(转换前的值 AS 想要转换的数据类型)

SELECT CAST(‘0001’ AS INTEGER) AS int_col;

screen-capture

将字符串类型转换为日期类型

SELECT CAST(‘2009-12-14’ AS DATE) AS date_col;

将null转为其他值

COALESCE(数据1,数据2,数据3……)

该函数会返回可变参数 A 中左侧开始第1个不是 NULL 的值。参数个数是可变的,因此可以根据需要无限增加。

模糊查询

LIKE

SELECT * FROM SampleLike
WHERE strcol LIKE ‘%ddd%’;

BETWEEN AND

SELECT product_name, sale_price
FROM Product
WHERE sale_price BETWEEN 100 AND 1000;

包含100和1000

IN 和 NOT IN (注意:在使用IN 和 NOT IN 时是无法选取出 NULL 数据的)

SELECT product_name, purchase_price
FROM Product
WHERE purchase_price IN (320, 500, 5000);

使用子查询作为IN谓词的参数

SELECT product_name, sale_price
FROM Product
WHERE product_id IN (SELECT product_id
FROM ShopProduct
WHERE shop_id = ‘000C’);

EXIST谓词

SELECT product_name, sale_price FROM Product AS P WHERE EXISTS (SELECT * FROM ShopProduct AS SP
WHERE SP.shop_id = ‘000C’ AND SP.product_id = P.product_id);

CASE表达式

CASE WHEN <求值表达式> THEN <表达式>
WHEN <求值表达式> THEN <表达式>
WHEN <求值表达式> THEN <表达式>
. . .
ELSE <表达式>
END

SELECT product_name,
CASE WHEN product_type = ‘衣服’
THEN ‘A :’ | | product_type
WHEN product_type = ‘办公用品’
THEN ‘B :’ | | product_type
WHEN product_type = ‘厨房用具’
THEN ‘C :’ | | product_type
ELSE NULL
END AS abc_product_type
FROM Product;

product_name | abc_product_type
---------------±-----------------
T恤衫 | A :衣服
打孔器 | B :办公用品
运动T恤 | A :衣服
菜刀 | C :厨房用具
高压锅 | C :厨房用具
叉子 | C :厨房用具
擦菜板 | C :厨房用具
圆珠笔 | B :办公用品

使用CASE表达式进行行列转换(返回0也是true,不返回用null)

SELECT SUM(CASE WHEN product_type = ‘衣服’
THEN sale_price ELSE 0 END) AS sum_price_clothes,
SUM(CASE WHEN product_type = ‘厨房用具’
THEN sale_price ELSE 0 END) AS sum_price_kitchen,
SUM(CASE WHEN product_type = ‘办公用品’
THEN sale_price ELSE 0 END) AS sum_price_office
FROM Product;

sum_price_clothes | sum_price_kitchen | sum_price_office
--------------------±--------------------±----------------
5000 | 11180 | 600

union

通过 UNION 进行并集运算时可以使用任何形式的 SELECT 语句,
之前学过的 WHERE、GROUP BY、HAVING 等子句都可以使用。但是
ORDER BY 只能在最后使用一次

包含重复行的集合运算——ALL选项

在 UNION 的结果中保留重复行的语法。其实非常
简单,只需要在 UNION 后面添加 ALL 关键字就可以了

SELECT product_id, product_name
FROM Product
UNION ALL
SELECT product_id, product_name
FROM Product2;

选取表中公共部分——INTERSECT

SELECT product_id, product_name
FROM Product
INTERSECT
SELECT product_id, product_name
FROM Product2
ORDER BY product_id;

希望保留重复行时同样需要使用INTERSECT ALL

记录的减法——EXCEPT

SELECT product_id, product_name
FROM Product
EXCEPT
SELECT product_id, product_name
FROM Product2
ORDER BY product_id;

product-product2 与 product2-product不同

JOIN

SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name,
P.sale_price
FROM ShopProduct AS SP INNER JOIN Product AS P
ON SP.product_id = P.product_id;

OUTER JOIN

SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name, 
P.sale_price
FROM ShopProduct AS SP RIGHT OUTER JOIN Product AS P ①
ON SP.product_id = P.product_id;

3张以上的表的联结

SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name,
P.sale_price, IP.inventory_quantity
FROM ShopProduct AS SP INNER JOIN Product AS P
ON SP.product_id = P.product_id
INNER JOIN InventoryProduct AS IP
ON SP.product_id = IP.product_id
WHERE IP.inventory_id = ‘P001’;

交叉联结——CROSS JOIN 笛卡尔积

*SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name
FROM ShopProduct AS SP CROSS JOIN Product AS P; *

过时的内连结

SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name, 
P.sale_price
FROM ShopProduct SP, Product P
WHERE SP.product_id = P.product_id
AND SP.shop_id = ‘000A’;

关系除法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NOFz4O6t-1647847391959)(0b22e8c0f501dae9fa7fcd844d405b6a.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-30dT3V9b-1647847391961)(9a1e34b1083511ab5592120b230576c3.png)]

*CREATE TABLE Skills
(**skill **VARCHAR(32),
PRIMARY KEY(skill)); CREATE TABLE EmpSkills
(**emp *VARCHAR(32),
skill VARCHAR(32),
PRIMARY KEY(emp, skill));

BEGIN TRANSACTION;
INSERT INTO Skills VALUES(‘Oracle’);
INSERT INTO Skills VALUES(‘UNIX’);
INSERT INTO Skills VALUES(‘Java’);
INSERT INTO EmpSkills VALUES(‘相田’, ‘Oracle’);
INSERT INTO EmpSkills VALUES(‘相田’, ‘UNIX’);
INSERT INTO EmpSkills VALUES(‘相田’, ‘Java’);
INSERT INTO EmpSkills VALUES(‘相田’, ‘C#’);
INSERT INTO EmpSkills VALUES(‘神崎’, ‘Oracle’);
INSERT INTO EmpSkills VALUES(‘神崎’, ‘UNIX’);
INSERT INTO EmpSkills VALUES(‘神崎’, ‘Java’);
INSERT INTO EmpSkills VALUES(‘平井’, ‘UNIX’);
INSERT INTO EmpSkills VALUES(‘平井’, ‘Oracle’);
INSERT INTO EmpSkills VALUES(‘平井’, ‘PHP’);
INSERT INTO EmpSkills VALUES(‘平井’, ‘Perl’);
INSERT INTO EmpSkills VALUES(‘平井’, ‘C++’);
INSERT INTO EmpSkills VALUES(‘若田部’, ‘Perl’);
INSERT INTO EmpSkills VALUES(‘渡来’, ‘Oracle’);
COMMIT;

SELECT DISTINCT emp
FROM EmpSkills ES1
WHERE NOT EXISTS
(SELECT skill
FROM Skills
EXCEPT
SELECT skill
FROM EmpSkills ES2
WHERE EP1.emp = ES2.emp);

结果:

emp ------- *神崎
*相田

除法和乘法是相辅相成的关系,除法运算的结果(商)乘以除数就能得到除
法运算前的被除数了。例如对于 20÷4 = 5 来说,就是 5( 商 )×4( 除数 ) = 20( 被
除数)。
关系除法中这样的规则也是成立的。通过商和除数相乘,也就是交叉联结,
就能够得到作为被除数的集合了

窗口函数(OLAP函数)

<窗口函数> OVER ([PARTITION BY <列清单>]
ORDER BY <排序用列清单>)

窗口函数大体可以分为以下两种。
① 能够作为窗口函数的聚合函数(SUM、AVG、COUNT、MAX、MIN)
② RANK、DENSE_RANK、ROW_NUMBER 等 专用窗口函数

窗口函数和group by不同,group by 是分组后每组只返回一行,而聚合开窗函数使用OVER子句是不会改变原来的行数的(即在返回基本列的同时,在同一行对它们进行聚合)所以需要去重加distinct

  • RANK函数
    计算排序时,如果存在相同位次的记录,则会跳过之后的位次。
    例)有 3 条记录排在第 1 位时:1 位、1 位、1 位、4 位……
  • DENSE_RANK函数
    同样是计算排序,即使存在相同位次的记录,也不会跳过之后的位次。
    例)有 3 条记录排在第 1 位时:1 位、1 位、1 位、2 位……
  • ROW_NUMBER函数
    赋予唯一的连续位次。
    例)有 3 条记录排在第 1 位时:1 位、2 位、3 位、4 位……

SELECT product_name, product_type, sale_price,
RANK () OVER (PARTITION BY product_type
ORDER BY sale_price) AS ranking
FROM Product;

PARTITION BY 能够设定排序的对象范围。本例中,为了按照商品
种类进行排序,我们指定了 product_type。

通过 PARTITION BY 分组后的记录集合称为窗口。此处的窗口并
非“窗户”的意思,而是代表范围。这也是“窗口函数”名称的由来。

ORDER BY 能够指定按照哪一列、何种顺序进行排序。


窗口函数的适用范围

原则上窗口函数只能在SELECT子句中使用, 这类函数不能在WHERE 子句或者 GROUP BY 子句中使用。

在 DBMS 内部,窗口函数是对 WHERE 子句或者 GROUP
BY 子句处理后的“结果”进行的操作

将SUM函数作为窗口函数使用 (累计的统计方法)

SELECT product_id, product_name, sale_price,
SUM (sale_price) OVER (ORDER BY product_id) AS current_sum
FROM Product;


product_id | product_name | sale_price | current_sum
------------±-------------±-----------±-----------
0001 | T恤衫 | 1000 | 1000 ←1000
0002 | 打孔器 | 500 | 1500 ←1000+500
0003 | 运动T恤 | 4000 | 5500 ←1000+500+4000
0004 | 菜刀 | 3000 | 8500 ←1000+500+4000+3000
0005 | 高压锅 | 6800 | 15300
0006 | 叉子 | 500 | 15800
0007 | 擦菜板 | 880 | 16680
0008 | 圆珠笔 | 100 | 16780

计算移动平均

SELECT product_id, product_name, sale_price,
AVG (sale_price) OVER (ORDER BY product_id
ROWS 2 PRECEDING) AS moving_avg
FROM Product;

这里我们使用了 ROWS(“行”)和 PRECEDING(“之前”)两个关键
字,将框架指定为“截止到之前 ~ 行”,因此“ROWS 2 PRECEDING” 就是将框架指定为“截止到之前 2 行”,也就是将作为汇总对象的记录限
定为如下的“最靠近的 3 行”。

● 自身(当前记录)
● 之前 1行的记录
● 之前 2行的记录

结果

product_id product_name sale_price moving_avg


0001     T恤衫         1000        1000(1000)/1
0002     打孔器        500       750(1000+500)/2
0003     运动T恤       4000         1833(1000+500+4000)/3
0004     菜刀         3000         2500(500+4000+3000)/3
0005     高压锅        6800      4600(4000+3000+6800)/3
0006     叉子         500          3433
0007     擦菜板        880       2726
0008     圆珠笔        100       493 
我们通过指定框架,将“1 PRECEDING”(之前 1 行)和“1 FOLLOWING”(之后 1 行)的区间作为汇总对象

SELECT product_id, product_name, sale_price,
AVG (sale_price) OVER (ORDER BY product_id
ROWS BETWEEN 1 PRECEDING AND
1 FOLLOWING) AS moving_avg
FROM Product;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6lmPYesP-1647847391962)(343d150dd51d34aeeb68704fa0eb8c84.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h25Mzjpx-1647847391962)(b8055e3537edfd64b44b4edce82c408c.png)]


GRROUPING运算符

ROLLUP

SELECT product_type, SUM(sale_price) AS sum_price
FROM Product
GROUP BY ROLLUP(product_type);

一次计算出了如下两种组合的汇总结果

① GROUP BY ()
② GROUP BY (product_type)

product_type  sum_price
-------------- ---------
                16780 
厨房用具        11180
办公用品        600
衣服            5000

SELECT product_type, regist_date, SUM(sale_price) AS sum_price
FROM Product
GROUP BY ROLLUP(product_type, regist_date);

① GROUP BY ()
② GROUP BY (product_type)
③ GROUP BY (product_type, regist_date)

GROUPING

SELECT GROUPING(product_type) AS product_type,
GROUPING(regist_date) AS regist_date, SUM(sale_price) AS sum_price
FROM Product
GROUP BY ROLLUP(product_type, regist_date);

该函数在其参数列的值为超级分组记录所产生的 NULL 时返回 1,其他情况返回 0

还可以把1转换为合计行

SELECT CASE WHEN GROUPING(product_type) = 1
THEN ‘商品种类 合计’
ELSE product_type END AS product_type,
CASE WHEN GROUPING(regist_date) = 1
THEN ‘登记日期 合计’
ELSE CAST(regist_date AS VARCHAR(16)) END AS regist_date,
SUM(sale_price) AS sum_price
FROM Product
GROUP BY ROLLUP(product_type, regist_date);

CUBE

SELECT CASE WHEN GROUPING(product_type) = 1
THEN ‘商品种类 合计’
ELSE product_type END AS product_type,
CASE WHEN GROUPING(regist_date) = 1
THEN ‘登记日期 合计’
ELSE CAST(regist_date AS VARCHAR(16)) END AS regist_date,
SUM(sale_price) AS sum_price
FROM Product
GROUP BY CUBE(product_type, regist_date);

① GROUP BY ()
② GROUP BY (product_type)
③ GROUP BY (regist_date) ←添加的组合
④ GROUP BY (product_type, regist_date)

GROUPING SETS

运算符可以用于从 ROLLUP 或者 CUBE 的结果中取出部分记录。

SELECT CASE WHEN GROUPING(product_type) = 1
THEN ‘商品种类 合计’
ELSE product_type END AS product_type,
CASE WHEN GROUPING(regist_date) = 1
THEN ‘登记日期 合计’
ELSE CAST(regist_date AS VARCHAR(16)) END AS regist_date,
SUM(sale_price) AS sum_price
FROM Product
GROUP BY GROUPING SETS (product_type, regist_date);

 product_type   regist_date sum_price
-------------- ------------ ----------

商品种类 合计   2008-04-28    880
商品种类 合计   2009-01-15    6800
商品种类 合计   2009-09-11    500
商品种类 合计   2009-09-20    4500
商品种类 合计   2009-11-11    100
商品种类 合计                 4000
厨房用具        登记日期 合计 11180
办公用品        登记日期 合计 600
衣服            登记日期 合计 5000

上述结果中也没有全体的合计行(16780 日元)。


分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进