天天看点

SQL学习记录(一)

跟着Udacity上的SQL课程学完有一段时间了,通过总结来加深一哈印象。(个人认为这个课程不错,网址(https://classroom.udacity.com/courses/ud198))

课程只有七节课,会按照顺序记录

  • Basic
  • Join
  • Aggregation
    • 常用
    • 日期
    • CASE
  • Subqueries
  • Data Cleaning
  • Windows Functions
  • SQL Advanced

1、Basic

SQL是结构化的查询语句,它主要是对关系型的数据库来说的。这个语句主要可以分为四类:

  • DDL

    数据定义语言,主要是用来定义数据库的对象,例如数据库,表,列之类的。主要是对应数据库和表的CRUD。(现在的客户端操作方便,这方面很多都没有去注意。)

  • DML

    数据操作语言,主要是增删改。主要是

//增(一一对应,也可省略不写,默认添加所有列)
INSERT INTO 表名(列名1,列名2,列名3,...) VALUES (值1,值2,值3,...) ;
//删
DELETE FROM 表名 WHERE 条件 ;

TRUNCATE TABLE 表名;//删除整张表的记录的效率会更高
//改
UPDATE 表名 SET 列1=值1,列2=值2,列3=值3... WHERE 条件;
           
  • DQL

    数据查询语言,主要是查询表,这也是课程主要讲的内容。

    最基础的查询主要有

    SQL学习记录(一)
    这个写(详细点的后面会总结)
    SQL学习记录(一)
  • DCL

    数据控制语言,主要是定义访问权限和安全级别。

SQL语言支持的是三级模式结构,如下图所示

SQL学习记录(一)

2、Join

这一块的内容主要是针对于两张表以上的查询,这有利于我们从多张表里取数据,主要分为:

1. 内连接

内连接分为隐式内连接和显式内连接,二者只是写法不同,查询的都是两张表的交集部分

//显示(条件中的字段名加单引号)
SELECT 字段名 FROM 表1 JOIN 表2 ON 条件;
//隐式(条件中的字段名加单引号)
SELECT 字段名 FROM 表1,表2 WHERE 条件;
           

为了书写简单,最好都起别名进行书写。

2.外连接

外连接主要有 LEFT JOIN 、RIGHT JOIN 、FULL JOIN

写法跟内连接显示写法相同,返回的结果集不同。

3、Aggregation

SQL中提供得聚合函数有,COUNT、SUM、AVG、MAX、MIN。一般运用在select后面的对象中,其中需要注意的是在聚合函数遇到空值的时候,除了COUNT()外所有的函数皆跳过空值,只处理非空值。(可以用IFNULL(列名,置为的值)*函数处理)。

聚合函数一般与GROUP BY和HAVING 一起使用,实现分组聚合

  • GROUP BY 是对查询结果按照某一列或者某几列进行分组,值相等的分为一组。
  • HAVING对分组的结果进行选择,仅输出满足条件的组。(必须与GROUP BY配合使用)通常更多是用于对于聚合之后的元素进行选择。例如
//有多少用户有20个以上的订单(COUNT的对象就是连接之后的虚拟表)
SELECT a.id, a.name, COUNT(*) num_orders
FROM accounts a
JOIN orders o
ON a.id = o.account_id
GROUP BY a.id, a.name
HAVING COUNT(*) > 20
ORDER BY num_orders;
           

特殊并常用的。对于日期的聚合,对于时间戳聚合显然是不常用的。对此SQL引入了两个函数

  • DATE_TRUNC
//查询2014年到2017年之间每个月销售总数量
SELECT DATE_TRUNC('month', occurred_at) ord_month, SUM(total_amt_usd) total_spent
FROM orders
WHERE occurred_at BETWEEN '2014-01-01' AND '2017-01-01'
GROUP BY 1
ORDER BY 2 DESC; 
           
  • DATE_PART

    对于这函数以及更多有关日期的函数的使用可以参看文档(https://www.postgresql.org/docs/9.1/functions-datetime.html)

CASE情况也是聚合常用的。CASE必须包含以下组件:WHEN、THEN和END。ELSE是一个可选组件,用于捕获不满足任何其他先前案例条件的案例。通过一个例子可以了解

SELECT s.name, COUNT(*), SUM(o.total_amt_usd) total_spent, 
     CASE WHEN COUNT(*) > 200 OR SUM(o.total_amt_usd) > 750000 THEN 'top'
     WHEN COUNT(*) > 150 OR SUM(o.total_amt_usd) > 500000 THEN 'middle'
     ELSE 'low' END AS sales_rep_level
FROM orders o
JOIN accounts a
ON o.account_id = a.id 
JOIN sales_reps s
ON s.id = a.sales_rep_id
GROUP BY s.name
ORDER BY 3 DESC;
           

通过以下的结果集可以看到,实现的是一个分级的效果

SQL学习记录(一)

4、Subqueries

这一节主要是讲的子查询和临时表,其中需要注意的是可以用WITH来书写来避免多级的嵌套带来的理解上的困难

例如下面这个语句就是将t1、t2作为临时表

WITH t1 AS (
   SELECT r.name region_name, SUM(o.total_amt_usd) total_amt
   FROM sales_reps s
   JOIN accounts a
   ON a.sales_rep_id = s.id
   JOIN orders o
   ON o.account_id = a.id
   JOIN region r
   ON r.id = s.region_id
   GROUP BY r.name), 
t2 AS (
   SELECT MAX(total_amt)
   FROM t1)
SELECT r.name, COUNT(o.total) total_orders
FROM sales_reps s
JOIN accounts a
ON a.sales_rep_id = s.id
JOIN orders o
ON o.account_id = a.id
JOIN region r
ON r.id = s.region_id
GROUP BY r.name
HAVING SUM(o.total_amt_usd) = (SELECT * FROM t2);
           

(这么多JOIN,其实我觉得视图可能更简单)

另外,子查询中不要使用ORDER BY

5、Data Cleaning

在这一章介绍了几个常见的函数

用几个例子来记录一哈

WITH t1 AS (
//STRPOS返回数字
 SELECT LEFT(primary_poc, STRPOS(primary_poc, ' ') -1 ) first_name,  RIGHT(primary_poc, LENGTH(primary_poc) - STRPOS(primary_poc, ' ')) last_name, 
 name
 FROM accounts)
 
SELECT first_name, last_name, 
//REPLACE此处是去掉空格
CONCAT(first_name, '.', last_name, '@', REPLACE(name, ' ', ''), '.com')
FROM  t1;
           
SELECT date orig_date, 
//::DATE是说拼接之后的作为日期CAST(date_column AS DATE) 和 date_column::DATE是一样的
(SUBSTR(date, 7, 4) || '-' || LEFT(date, 2) || '-' || SUBSTR(date, 4, 2))::DATE new_date
FROM sf_crime_data;
           

6、Windows Functions

不想写了,想起来再补