Advertisement

Introduction to SQL for Data Science

阅读量:

作者:禅与计算机程序设计艺术

1.简介

随着大数据的不断增长、数据量的增加、计算设备的普及,以及互联网的发展,数据处理变得越来越复杂、越来越重要。数据的获取、整合、存储、分析等各个环节均需要用到各种编程语言、数据库管理系统(Database Management System,DBMS),这些技术都是由专业工程师来进行研发、维护和应用的。

SQL(Structured Query Language)是一种用于管理关系型数据库的标准化语言。它具备强大的查询功能,能够对数据库中的数据快速、有效地检索、汇总、分析、过滤、更新和修改。本文将会从基础语法、数据类型、运算符、函数、条件语句、分组排序、聚集函数、子查询、视图、触发器等方面,详细介绍SQL在数据科学领域的应用。

本文不会涉及复杂的数据建模过程,只从实际应用角度出发,重点介绍SQL的基本语法、数据类型、运算符、函数、条件语句、分组排序、聚集函数、子查询、视图、触发器等技术。读者可以充分利用这部分知识学习和应用于实际项目。

2.基本概念术语说明

2.1 数据模型

在数据分析和处理过程中,数据通常被组织成不同的表格形式。这种形式称为数据模型。数据模型的目的是对数据的逻辑结构进行抽象,从而方便地对其进行表示、管理、操纵和查询。

关系型数据模型与NoSQL数据模型:

  1. 关系型数据库(Relational Database)

关系型数据库是最常用的一种数据模型。它以表格的形式存储数据,每行对应一条记录,每列代表一个属性或字段。关系型数据库可以按照结构化查询语言(Structured Query Language,SQL)对数据进行检索、插入、删除、更新等操作。

  1. NoSQL数据模型

NoSQL(Not Only Structured Query Language)是一个泛指非关系型的数据库,其支持无模式、高可扩展性和分布式数据库设计理念。它提供了一系列数据模型,包括文档型、键值对型、图形型、列存型和时间序列型等。其中文档型和键值对型是最常见的两种NoSQL数据模型。

复制代码
 * 文档型数据库(Document-Oriented Database)

以文档的方式存储数据。它将数据存储为一系列集合,每个集合中存储多个文档。文档可以是嵌套的、拥有多个键值的形式。

MongoDB、Couchbase、Firebase都是典型的文档型数据库。

复制代码
 * 键值对型数据库(Key-Value Store)

以键值对的方式存储数据。它将数据存储为键值对,其中每个值都是一个字节数组。键值对型数据库不能保证数据之间的关系,只能通过键来访问数据。Redis、Memcached就是典型的键值对型数据库。

2.2 SQL语言简介

SQL(Structured Query Language,结构化查询语言)是用于管理关系型数据库的标准语言。它是一种声明式的语言,它的一般工作流程如下:

  1. 创建并定义数据库对象(如表、视图、索引、约束等)。
  2. 使用SELECT语句从数据库表或视图中检索数据。
  3. 使用INSERT、UPDATE或DELETE语句向数据库表中插入、更新或删除数据。
  4. 对数据执行各种操作,如排序、过滤、聚集、分组等。

SQL语言共有四种主要的类别:DML(Data Manipulation Language)、DDL(Data Definition Language)、DCL(Data Control Language)和TCL(Transaction Control Language)。

  • DML:用于操作数据库表中的数据,包括SELECT、INSERT、UPDATE、DELETE等。
  • DDL:用于定义、修改、删除数据库对象,包括CREATE、ALTER、DROP、TRUNCATE等。
  • DCL:用于控制数据库用户权限、事务等,包括GRANT、REVOKE、COMMIT、ROLLBACK等。
  • TCL:用于管理事务,包括BEGIN TRANSACTION、END TRANSACTION等。

2.3 SQL常用语句分类

2.3.1 SELECT语句

SELECT语句用于从数据库表或视图中选择数据。语法格式如下:

复制代码
    SELECT [DISTINCT] column_name(s) 
    FROM table_name
    [WHERE condition] 
    [ORDER BY column_name [ASC|DESC]] 
    [LIMIT {[offset],} row_count]
    
      
      
      
      
    
    代码解读
  • column_name:要查询的列名。
    • [DISTINCT]:去除重复项。
    • table_name:要查询的表名。
    • [WHERE condition]:指定查询条件,根据指定的条件来筛选数据。
    • [ORDER BY column_name [ASC|DESC]]:按指定列排序,默认升序。
    • [LIMIT {[offset],} row_count]:限制返回结果的行数,可指定偏移量和数量。

示例:

复制代码
    -- 查询 employee 表中的所有数据
    SELECT * FROM employee; 
    
    -- 查询 employee 表中的 name 和 salary 列的数据
    SELECT name, salary FROM employee;
    
    -- 查询 employee 表中 name 为 'John' 的数据
    SELECT * FROM employee WHERE name='John';
    
    -- 查询 employee 表中 salary 降序排列的数据
    SELECT * FROM employee ORDER BY salary DESC;
    
    -- 查询 employee 表中 name 为 'John' 或 'Mary' 的数据
    SELECT * FROM employee WHERE name IN ('John', 'Mary');
    
    -- 查询 employee 表中第 1~3 行的数据
    SELECT * FROM employee LIMIT 3 OFFSET 0;
    
    -- 查询 employee 表中第 4~7 行的数据
    SELECT * FROM employee LIMIT 3 OFFSET 3;
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

2.3.2 INSERT INTO语句

INSERT INTO语句用于向数据库表中插入新的数据。语法格式如下:

复制代码
    INSERT INTO table_name (column1, column2,...) VALUES (value1, value2,...);
    
    
    代码解读
  • table_name:要插入的表名。
    • (column1, column2,...):要插入的列名列表。
    • (value1, value2,...):要插入的值列表。

示例:

复制代码
    -- 在 employee 表中插入一条数据
    INSERT INTO employee (id, name, age, salary) 
    VALUES (1, 'John', 30, 5000);
    
    -- 在 department 表中插入多条数据
    INSERT INTO department (id, name) 
    VALUES 
      (1, 'Sales'),
      (2, 'Marketing'),
      (3, 'Finance'),
      (4, 'Operations');
    
      
      
      
      
      
      
      
      
      
      
    
    代码解读

2.3.3 UPDATE语句

UPDATE语句用于更新数据库表中的数据。语法格式如下:

复制代码
    UPDATE table_name SET column1=value1, column2=value2,... 
    [WHERE condition];
    
      
    
    代码解读
  • table_name:要更新的表名。
    • (column1=value1, column2=value2,...):要更新的列和值。
    • [WHERE condition]:指定更新条件,根据指定的条件来确定要更新的数据。

示例:

复制代码
    -- 更新 employee 表中 id 为 1 的员工信息
    UPDATE employee SET age=35, salary=6000 WHERE id=1;
    
    -- 将 department 表中所有部门名称改为小写字母
    UPDATE department SET name=LOWER(name);
    
      
      
      
      
    
    代码解读

2.3.4 DELETE语句

DELETE语句用于删除数据库表中的数据。语法格式如下:

复制代码
    DELETE FROM table_name 
    [WHERE condition];
    
      
    
    代码解读
  • table_name:要删除的表名。
    • [WHERE condition]:指定删除条件,根据指定的条件来确定要删除的数据。

示例:

复制代码
    -- 删除 employee 表中 id 为 1 的员工信息
    DELETE FROM employee WHERE id=1;
    
    -- 清空 department 表中的所有数据
    DELETE FROM department;
    
      
      
      
      
    
    代码解读

2.3.5 ALTER TABLE语句

ALTER TABLE语句用于修改数据库表的结构。语法格式如下:

复制代码
    ALTER TABLE table_name {ADD COLUMN column_definition | DROP COLUMN column_name};
    
    
    代码解读
  • table_name:要修改的表名。
    • {ADD COLUMN column_definition | DROP COLUMN column_name}:要添加或删除的列名及其定义或名称。

示例:

复制代码
    -- 添加 salary 列到 employee 表中
    ALTER TABLE employee ADD COLUMN salary INTEGER DEFAULT 0;
    
    -- 删除 age 列
    ALTER TABLE employee DROP COLUMN age;
    
      
      
      
      
    
    代码解读

2.3.6 CREATE INDEX语句

CREATE INDEX语句用于创建索引。语法格式如下:

复制代码
    CREATE INDEX index_name ON table_name (column_name);
    
    
    代码解读
  • index_name:索引名称。
    • table_name:要创建索引的表名。
    • (column_name):要创建索引的列名。

示例:

复制代码
    -- 创建 name 列的索引
    CREATE INDEX idx_employee_name ON employee (name);
    
      
    
    代码解读

2.3.7 JOIN语句

JOIN语句用于合并两个表中的数据。语法格式如下:

复制代码
    SELECT column_name(s) 
    FROM table1 
    INNER JOIN table2 
    ON table1.common_column = table2.common_column;
    
      
      
      
    
    代码解读
  • column_name(s):要查询的列名。
    • table1table2:要连接的表名。
    • .common_column:要比较的列名。

示例:

复制代码
    -- 查询 employee 表中的所有数据,同时显示 department 表中的相应数据
    SELECT e.*, d.name AS dept_name 
    FROM employee e 
    INNER JOIN department d 
    ON e.dept_id = d.id;
    
    -- 查询 customer 表中 order_date 小于等于 '2019-01-31' 的订单信息,同时显示相关产品信息
    SELECT c.*, o.*, p.* 
    FROM customer c 
    INNER JOIN orders o 
    ON c.customer_id = o.customer_id 
    INNER JOIN products p 
    ON o.product_id = p.product_id 
    WHERE o.order_date <= '2019-01-31';
    
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

2.3.8 UNION语句

UNION语句用于合并两个或多个SELECT语句的结果集。语法格式如下:

复制代码
    SELECT column_name(s) 
    FROM table_name1 
    UNION ALL 
    SELECT column_name(s) 
    FROM table_name2;
    
      
      
      
      
    
    代码解读
  • column_name(s):要查询的列名。
    • table_nameN:要合并的表名。
    • ALL:保留重复行。

示例:

复制代码
    -- 查询 employee 表和 department 表的所有数据
    SELECT * FROM employee 
    UNION ALL 
    SELECT * FROM department;
    
    -- 查询 product 表中 price 大于等于 5000 的数据,并且按照 price 降序排列;再与 employee 表中对应的员工姓名数据合并显示
    SELECT p.*, e.name 
    FROM product p 
    INNER JOIN employee e 
    ON p.employee_id = e.id 
    WHERE p.price >= 5000 
    ORDER BY p.price DESC;
    
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

2.3.9 CREATE VIEW语句

CREATE VIEW语句用于创建视图。语法格式如下:

复制代码
    CREATE VIEW view_name AS 
    SELECT statement;
    
      
    
    代码解读
  • view_name:视图名称。
    • AS:关键字。
    • SELECT statement:查询语句。

示例:

复制代码
    -- 创建视图 vw_department_salary,该视图显示了 department 表中每个部门的平均薪水
    CREATE VIEW vw_department_salary AS
    SELECT d.name AS department, AVG(e.salary) AS avg_salary 
    FROM department d 
    INNER JOIN employee e 
    ON d.id = e.dept_id 
    GROUP BY d.name;
    
    -- 查看视图 vw_department_salary 中的数据
    SELECT * FROM vw_department_salary;
    
      
      
      
      
      
      
      
      
      
    
    代码解读

2.3.10 TRIGGER语句

TRIGGER语句用于创建触发器。语法格式如下:

复制代码
    CREATE TRIGGER trigger_name 
    BEFORE/AFTER insert/update/delete 
    ON table_name 
    FOR EACH ROW 
    BEGIN
       -- trigger body
    END;
    
      
      
      
      
      
      
    
    代码解读
  • trigger_name:触发器名称。
    • BEFORE/AFTER:触发时机,分别表示在事件之前或之后触发。
    • insert/update/delete:事件类型。
    • table_name:要监听的表名。
    • FOR EACH ROW:触发器作用范围,每次触发针对单行数据。
    • BEGIN:关键字。
    • -- trigger body:触发器主体,可以编写任意的SQL语句。

示例:

复制代码
    -- 创建触发器 tg_employee_biu,在 employee 表上新增、更新或删除数据时,自动更新 vw_department_salary 视图
    CREATE OR REPLACE TRIGGER tg_employee_biu
    AFTER INSERT OR UPDATE OR DELETE ON employee
    FOR EACH ROW
    EXECUTE PROCEDURE update_vw_department_salary();
    
    CREATE FUNCTION update_vw_department_salary() RETURNS TRIGGER AS
$$
    DECLARE 
    v_avg_salary NUMERIC(10,2);
    BEGIN
    IF TG_OP = 'INSERT' THEN
        UPDATE vw_department_salary 
        SET avg_salary = COALESCE((SELECT AVG(salary) FROM employee WHERE dept_id = NEW.dept_id), 0)
        WHERE department = (SELECT name FROM department WHERE id = NEW.dept_id);
    ELSIF TG_OP = 'UPDATE' THEN
        SELECT AVG(salary) INTO v_avg_salary FROM employee WHERE dept_id = OLD.dept_id;
        IF (v_avg_salary <> NULL AND v_avg_salary <> 0) THEN
            UPDATE vw_department_salary 
            SET avg_salary = ((COALESCE((SELECT COUNT(*) FROM employee WHERE dept_id = OLD.dept_id), 0)*OLD.avg_salary + COALESCE((SELECT COUNT(*) FROM employee WHERE dept_id = NEW.dept_id), 0)*NEW.salary)/(COALESCE((SELECT COUNT(*) FROM employee WHERE dept_id = OLD.dept_id), 0)+COALESCE((SELECT COUNT(*) FROM employee WHERE dept_id = NEW.dept_id), 0)))
            WHERE department = (SELECT name FROM department WHERE id = NEW.dept_id);
        END IF;    
    ELSIF TG_OP = 'DELETE' THEN
        UPDATE vw_department_salary 
        SET avg_salary = COALESCE((SELECT AVG(salary) FROM employee WHERE dept_id = OLD.dept_id), 0)
        WHERE department = (SELECT name FROM department WHERE id = OLD.dept_id);   
    END IF;
    
    RETURN NEW;
    END;
   
$$
LANGUAGE plpgsql;
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

3.核心算法原理和具体操作步骤以及数学公式讲解

3.1 算法概述

3.2 概率论

3.3 数据预处理

3.4 特征工程

3.5 机器学习

3.6 模型评估

3.7 模型调优

4.具体代码实例和解释说明

4.1 SQL SELECT语句

复制代码
    SELECT DISTINCT city FROM customers WHERE country = 'USA';
    
    
    代码解读
  • 这里使用DISTINCT关键词来去掉重复的城市名称。
    • 从customers表中选取country为“USA”的城市名称。
复制代码
    SELECT MAX(age) FROM employees;
    
    
    代码解读
  • 这里使用MAX函数来找到年龄最大的人员。
    • 从employees表中查找年龄最大的员工。
复制代码
    SELECT MIN(salary) FROM employees WHERE job_title LIKE '%Manager%';
    
    
    代码解读
  • 这里使用MIN函数找到管理人员的最低工资。
    • 从employees表中查找工资最低的管理人员。
复制代码
    SELECT COUNT(*) FROM customers;
    
    
    代码解读
  • 这里使用COUNT函数统计顾客数量。
    • 从customers表中查找所有顾客数量。
复制代码
    SELECT customer_name, email FROM customers WHERE customer_name NOT LIKE '%Smith%' AND email LIKE '%gmail.com';
    
    
    代码解读
  • 这里使用NOT LIKE关键词排除以Smith结尾的顾客,然后使用LIKE关键词筛选出email以gmail.com结尾的顾客。
    • 从customers表中查找顾客姓名不以“Smith”结尾且邮箱地址以“@gmail.com”结尾的顾客信息。
复制代码
    SELECT SUM(price*quantity) as total_revenue FROM sales;
    
    
    代码解读
  • 这里使用SUM函数计算销售额总和。
    • 从sales表中查找销售额总和。
复制代码
    SELECT CONCAT(first_name,' ',last_name) as full_name FROM employees;
    
    
    代码解读
  • 这里使用CONCAT函数拼接全名。
    • 从employees表中查找所有的员工全名。
复制代码
    SELECT category_name, AVG(sale_amount) as average_sale FROM sales GROUP BY category_name;
    
    
    代码解读
  • 这里使用AVG函数计算每个品类的销售额平均值。
    • 从sales表中查出各个品类及其平均销售额。
复制代码
    SELECT YEAR(order_date) as year, MONTH(order_date) as month, COUNT(*) as num_orders FROM orders GROUP BY YEAR(order_date), MONTH(order_date);
    
    
    代码解读
  • 这里使用YEAR和MONTH函数统计每个月订单数量。
    • 从orders表中查找每个月的订单数量。
复制代码
    SELECT customer_name, AVG(purchased_items) as avg_items_purchased FROM purchases GROUP BY customer_name HAVING avg_items_purchased > 2;
    
    
    代码解读
  • 这里使用AVG函数找出购买商品最多的顾客。
    • 从purchases表中查找每个顾客的购买商品平均数量,且仅显示购买商品超过2件的顾客信息。
复制代码
    SELECT state, AVG(rental_rate) as avg_rental_rate FROM rentals WHERE property_type = 'Condo' GROUP BY state;
    
    
    代码解读
  • 这里使用AVG函数找出州份的平均租金费率。
    • 从rentals表中查找某个物业类型的州份的平均租金费率。

4.2 SQL INSERT INTO语句

复制代码
    INSERT INTO customers (customer_name, email, address) VALUES ('Jane Doe', 'jdoe@gmail.com', '123 Main St.');
    
    
    代码解读
  • 这里使用INSERT INTO语句向customers表中插入一条顾客信息。
    • 插入的记录包含顾客姓名、邮件地址和地址。
复制代码
    INSERT INTO orders (customer_id, item_id, quantity, purchase_date) VALUES (1, 1, 1, NOW());
    
    
    代码解读
  • 这里使用INSERT INTO语句向orders表中插入一条订单信息。
    • 插入的记录包含顾客ID、商品ID、数量和采购日期。

4.3 SQL UPDATE语句

复制代码
    UPDATE customers SET email='<EMAIL>' WHERE customer_id=1;
    
    
    代码解读
  • 这里使用UPDATE语句更新customers表中的某条记录。
    • 更新的记录仅包含顾客ID和新的邮件地址。
复制代码
    UPDATE departments SET manager_id=NULL WHERE dept_name='HR';
    
    
    代码解读
  • 这里使用UPDATE语句更新departments表中的某条记录。
    • 更新的记录仅包含部门名称和清除之前设定的经理。
复制代码
    UPDATE orders SET quantity=quantity+1 WHERE order_id=1;
    
    
    代码解读
  • 这里使用UPDATE语句更新orders表中的某条记录。
    • 更新的记录仅包含订单号和数量的增加。
复制代码
    UPDATE products SET price=price*1.1 WHERE category='Clothing';
    
    
    代码解读
  • 这里使用UPDATE语句更新products表中的某条记录。
    • 更新的记录仅包含某个特定类别的商品的价格的提高。
复制代码
    UPDATE rentals SET rental_duration=rental_duration+1 WHERE property_id=1;
    
    
    代码解读
  • 这里使用UPDATE语句更新rentals表中的某条记录。
    • 更新的记录仅包含某个物业的租赁期限的延长。

4.4 SQL DELETE语句

复制代码
    DELETE FROM customers WHERE customer_id=1;
    
    
    代码解读
  • 这里使用DELETE语句删除customers表中的某条记录。
    • 需要删除的记录仅包含顾客ID。
复制代码
    DELETE FROM orders WHERE order_id>100;
    
    
    代码解读
  • 这里使用DELETE语句删除orders表中的某些记录。
    • 需要删除的记录仅包含订单号。
复制代码
    DELETE FROM employees WHERE job_title!='Sales Manager';
    
    
    代码解读
  • 这里使用DELETE语句删除employees表中的某些记录。
    • 需要删除的记录仅包含不是销售经理的员工。
复制代码
    DELETE FROM products WHERE price<500;
    
    
    代码解读
  • 这里使用DELETE语句删除products表中的某些记录。
    • 需要删除的记录仅包含价格低于500元的商品。
复制代码
    DELETE FROM rentals WHERE rental_duration=1;
    
    
    代码解读
  • 这里使用DELETE语句删除rentals表中的某些记录。
    • 需要删除的记录仅包含租赁期限为1天的物业。

4.5 SQL ALTER TABLE语句

复制代码
    ALTER TABLE customers ADD phone VARCHAR(15);
    
    
    代码解读
  • 这里使用ALTER TABLE语句给customers表添加phone列。
    • 添加的列仅包含电话号码。
复制代码
    ALTER TABLE orders MODIFY COLUMN quantity INT UNSIGNED;
    
    
    代码解读
  • 这里使用ALTER TABLE语句更改orders表中的quantity列的数据类型。
    • 修改后的列包含整数数据,而且无符号。
复制代码
    ALTER TABLE rentals DROP PRIMARY KEY;
    
    
    代码解读
  • 这里使用ALTER TABLE语句删除rentals表中的主键。
    • 不需要主键来唯一标识每个物业。

4.6 SQL CREATE INDEX语句

复制代码
    CREATE INDEX idx_customer_name ON customers (customer_name);
    
    
    代码解读
  • 这里使用CREATE INDEX语句创建顾客姓名的索引。
    • 可以加快检索速度。
复制代码
    CREATE UNIQUE INDEX idx_employee_ssn ON employees (social_security_number);
    
    
    代码解读
  • 这里使用CREATE UNIQUE INDEX语句创建社保号的唯一索引。
    • 确保每个人的社保号只出现一次。
复制代码
    CREATE INDEX idx_sales_item ON sales (category_id, sale_amount);
    
    
    代码解读
  • 这里使用CREATE INDEX语句创建组合索引。
    • 可帮助优化查询效率。
复制代码
    CREATE INDEX idx_orders_date ON orders (order_date ASC);
    
    
    代码解读
  • 这里使用CREATE INDEX语句创建一个升序索引。
    • 可以加速特定日期的搜索。

4.7 SQL JOIN语句

复制代码
    SELECT e.*, d.name AS dept_name 
    FROM employees e 
    INNER JOIN departments d 
    ON e.dept_id = d.id;
    
      
      
      
    
    代码解读
  • 这里使用INNER JOIN语句连接employees和departments表。
    • 返回employees表中所有记录,并且连接departments表中相同ID的记录。
复制代码
    SELECT customer_name, email, items_purchased 
    FROM purchases 
    INNER JOIN (
    SELECT customer_id, SUM(quantity) as items_purchased 
    FROM purchases 
    GROUP BY customer_id
    ) t 
    ON purchases.customer_id = t.customer_id;
    
      
      
      
      
      
      
      
    
    代码解读
  • 这里使用INNER JOIN语句连接purchases和另一个子查询,来计算顾客购买的商品数量。
    • 首先使用子查询计算每个顾客购买的总数,然后使用父查询连接起来。
复制代码
    SELECT customer_name, state, AVG(rental_rate) as avg_rental_rate 
    FROM rentals r 
    INNER JOIN customers c 
    ON r.customer_id = c.customer_id 
    WHERE property_type = 'Condo' 
    GROUP BY customer_name, state;
    
      
      
      
      
      
    
    代码解读
  • 这里使用INNER JOIN语句连接rentals和customers表,来显示每个州份的平均租金费率。
    • 只显示那些类型为Condo的物业,并且显示顾客姓名和所在州份。

4.8 SQL UNION语句

复制代码
    SELECT a.state, b.state, c.state 
    FROM states a 
    INNER JOIN states b 
    ON a.population < b.population 
    INNER JOIN states c 
    ON b.population < c.population 
    UNION 
    SELECT a.state, b.state, c.state 
    FROM states a 
    INNER JOIN states b 
    ON a.area < b.area 
    INNER JOIN states c 
    ON b.area < c.area 
    ORDER BY area DESC;
    
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读
  • 这里使用UNION语句合并三个SELECT语句的结果集。
    • 第一个SELECT语句返回三个州份,它们分别按人口、面积大小进行排序。
    • 第二个SELECT语句返回三个州份,它们分别按人口、面积大小进行排序,但是先后顺序颠倒。
    • 可以查看三个州份中人口或面积最小的三个国家。

全部评论 (0)

还没有任何评论哟~