Skip to content

第一章练习答案 ​

本页包含第一章所有练习的答案和详细解释。

01-setup ​

练习 1:安装与连接 ​

答案:

安装 PostgreSQL(macOS):

bash
brew install postgresql@16
brew services start postgresql@16
psql --version

连接:

bash
psql -U postgres

练习 2:创建数据库 ​

答案:

sql
-- 创建数据库
CREATE DATABASE practice;

-- 创建用户
CREATE USER myuser WITH PASSWORD 'mypassword';

-- 授予权限
GRANT ALL PRIVILEGES ON DATABASE practice TO myuser;

-- 连接到新数据库
\c practice

-- PostgreSQL 15+ 需要额外授予 schema 权限
GRANT ALL ON SCHEMA public TO myuser;

练习 3:创建商品表 ​

答案:

sql
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    price DECIMAL(10, 2),
    stock INT,
    category VARCHAR(50)
);

练习 4:插入数据 ​

答案:

sql
INSERT INTO products (name, price, stock, category) VALUES
    ('iPhone 15', 999.99, 50, 'Electronics'),
    ('MacBook Pro', 2499.99, 20, 'Electronics'),
    ('Desk Chair', 299.99, 100, 'Furniture'),
    ('Coffee Maker', 89.99, 30, 'Appliances'),
    ('Notebook', 5.99, 500, 'Stationery'),
    ('Wireless Mouse', 29.99, 150, 'Electronics');

练习 5:查看数据 ​

答案:

sql
SELECT * FROM products;

输出:

text
 id |     name      |  price  | stock |   category
----+---------------+---------+-------+-------------
  1 | iPhone 15     |  999.99 |    50 | Electronics
  2 | MacBook Pro   | 2499.99 |    20 | Electronics
  3 | Desk Chair    |  299.99 |   100 | Furniture
  4 | Coffee Maker  |   89.99 |    30 | Appliances
  5 | Notebook      |    5.99 |   500 | Stationery
  6 | Wireless Mouse|   29.99 |   150 | Electronics

02-select ​

练习 1:选择特定列 ​

答案:

sql
SELECT name, email FROM users;

输出:

text
  name   |        email
---------+---------------------
 Alice   | alice@example.com
 Bob     | bob@example.com
 Charlie | charlie@example.com
 Diana   | diana@example.com
 Eve     | eve@example.com

练习 2:使用别名 ​

答案:

sql
SELECT name AS full_name, age AS years_old FROM users;

输出:

text
 full_name | years_old
-----------+-----------
 Alice     |        30
 Bob       |        25
 Charlie   |        35
 Diana     |        28
 Eve       |

练习 3:字符串拼接 ​

答案:

PostgreSQL:

sql
SELECT name || ': ' || email AS contact_info FROM users;

MySQL:

sql
SELECT CONCAT(name, ': ', email) AS contact_info FROM users;

输出:

text
          contact_info
--------------------------------
 Alice: alice@example.com
 Bob: bob@example.com
 Charlie: charlie@example.com
 Diana: diana@example.com
 Eve: eve@example.com

练习 4:年龄计算 ​

答案:

sql
SELECT name, age, age + 5 AS age_in_5_years FROM users;

输出:

text
  name   | age | age_in_5_years
---------+-----+----------------
 Alice   |  30 |             35
 Bob     |  25 |             30
 Charlie |  35 |             40
 Diana   |  28 |             33
 Eve     |     |

注意:Eve 的年龄是 NULL,NULL + 5 仍然是 NULL。

练习 5:函数应用 ​

答案:

sql
SELECT name, UPPER(name) AS name_upper, LENGTH(name) AS name_length FROM users;

输出:

text
  name   | name_upper | name_length
---------+------------+-------------
 Alice   | ALICE      |           5
 Bob     | BOB        |           3
 Charlie | CHARLIE    |           7
 Diana   | DIANA      |           5
 Eve     | EVE        |           3

练习 6:常量列 ​

答案:

sql
SELECT name, email, 'China' AS country FROM users;

输出:

text
  name   |        email        | country
---------+---------------------+---------
 Alice   | alice@example.com   | China
 Bob     | bob@example.com     | China
 Charlie | charlie@example.com | China
 Diana   | diana@example.com   | China
 Eve     | eve@example.com     | China

练习 7:当前时间 ​

答案:

sql
SELECT NOW() AS current_time, CURRENT_DATE AS today;

输出(示例):

text
      current_time       |   today
-------------------------+------------
 2026-09-20 15:30:45.123 | 2026-09-20

03-where ​

练习 1:简单过滤 ​

答案:

sql
SELECT name, age FROM users WHERE age >= 30;

输出:

text
  name   | age
---------+-----
 Alice   |  30
 Charlie |  35

练习 2:范围查询 ​

答案:

sql
SELECT name, age FROM users WHERE age BETWEEN 25 AND 30;

或:

sql
SELECT name, age FROM users WHERE age >= 25 AND age <= 30;

输出:

text
 name  | age
-------+-----
 Alice |  30
 Bob   |  25
 Diana |  28

练习 3:逻辑组合 ​

答案:

sql
SELECT name, age FROM users WHERE age < 26 OR age > 32;

输出:

text
  name   | age
---------+-----
 Bob     |  25
 Charlie |  35

练习 4:NULL 处理 ​

答案:

查询年龄为 NULL 的用户:

sql
SELECT name, age FROM users WHERE age IS NULL;

输出:

text
 name | age
------+-----
 Eve  |

查询年龄不为 NULL 的用户:

sql
SELECT name, age FROM users WHERE age IS NOT NULL;

输出:

text
  name   | age
---------+-----
 Alice   |  30
 Bob     |  25
 Charlie |  35
 Diana   |  28

练习 5:IN 操作 ​

答案:

sql
SELECT name FROM users WHERE name IN ('Alice', 'Bob', 'Diana');

输出:

text
 name
-------
 Alice
 Bob
 Diana

练习 6:模式匹配 ​

答案:

sql
SELECT name FROM users WHERE name LIKE 'C%';

输出:

text
  name
---------
 Charlie

练习 7:复杂条件 ​

答案:

PostgreSQL:

sql
SELECT name, age 
FROM users 
WHERE age BETWEEN 25 AND 35 
  AND LOWER(name) LIKE '%a%';

或使用 ILIKE(PostgreSQL):

sql
SELECT name, age 
FROM users 
WHERE age BETWEEN 25 AND 35 
  AND name ILIKE '%a%';

输出:

text
 name  | age
-------+-----
 Alice |  30
 Diana |  28

练习 8:边界测试 ​

答案:

sql
SELECT name, age 
FROM users 
WHERE age IS NOT NULL 
  AND (age < 25 OR age > 30);

或使用 NOT BETWEEN:

sql
SELECT name, age 
FROM users 
WHERE age NOT BETWEEN 25 AND 30;

输出:

text
  name   | age
---------+-----
 Charlie |  35

注意:NOT BETWEEN 会自动排除 NULL。


04-order-limit ​

练习 1:基本排序 ​

答案:

sql
SELECT name, age FROM users ORDER BY age ASC;

输出:

text
  name   | age
---------+-----
 Bob     |  25
 Diana   |  28
 Alice   |  30
 Charlie |  35
 Eve     |

练习 2:降序排序 ​

答案:

sql
SELECT name, age FROM users ORDER BY age DESC;

输出:

text
  name   | age
---------+-----
 Eve     |
 Charlie |  35
 Alice   |  30
 Diana   |  28
 Bob     |  25

练习 3:多列排序 ​

答案:

sql
SELECT name, age FROM users ORDER BY age DESC, name ASC;

输出:

text
  name   | age
---------+-----
 Eve     |
 Charlie |  35
 Alice   |  30
 Diana   |  28
 Bob     |  25

练习 4:前 N 行 ​

答案:

sql
SELECT name, age 
FROM users 
WHERE age IS NOT NULL
ORDER BY age ASC 
LIMIT 2;

输出:

text
 name  | age
-------+-----
 Bob   |  25
 Diana |  28

练习 5:分页查询 ​

答案:

sql
SELECT name, age 
FROM users 
WHERE age IS NOT NULL
ORDER BY age DESC 
LIMIT 2 OFFSET 2;

输出:

text
 name  | age
-------+-----
 Diana |  28
 Bob   |  25

练习 6:按表达式排序 ​

答案:

sql
SELECT name, LENGTH(name) AS name_length 
FROM users 
ORDER BY LENGTH(name) DESC, name ASC;

输出:

text
  name   | name_length
---------+-------------
 Charlie |           7
 Alice   |           5
 Diana   |           5
 Bob     |           3
 Eve     |           3

练习 7:NULL 处理 ​

答案:

PostgreSQL:

sql
SELECT name, age FROM users ORDER BY age ASC NULLS FIRST;

MySQL:

sql
SELECT name, age FROM users ORDER BY age IS NOT NULL, age ASC;

输出:

text
  name   | age
---------+-----
 Eve     |
 Bob     |  25
 Diana   |  28
 Alice   |  30
 Charlie |  35

练习 8:实际场景 ​

答案:

sql
SELECT name, age, created_at 
FROM users 
WHERE age > 25 
ORDER BY created_at DESC 
LIMIT 3;

输出(假设 created_at 按插入顺序):

text
  name   | age |       created_at
---------+-----+------------------------
 Charlie |  35 | 2026-09-20 10:30:00
 Alice   |  30 | 2026-09-20 10:30:00
 Diana   |  28 | 2026-09-20 10:30:00

05-distinct ​

练习 1:基本去重 ​

答案:

使用 orders 表:

sql
SELECT DISTINCT product FROM orders;

输出:

text
  product
------------
 Laptop
 Mouse
 Keyboard
 Monitor
 Headphones
 USB Cable

练习 2:多列去重 ​

答案:

sql
SELECT DISTINCT customer_name, product FROM orders;

输出:

text
 customer_name |  product
---------------+------------
 Alice         | Laptop
 Bob           | Mouse
 Alice         | Keyboard
 Charlie       | Monitor
 Bob           | Headphones
 Alice         | USB Cable

练习 3:统计去重 ​

答案:

sql
SELECT COUNT(DISTINCT customer_name) AS unique_customers FROM orders;

输出:

text
 unique_customers
------------------
                3

练习 4:去重后排序 ​

答案:

sql
SELECT DISTINCT customer_name FROM orders ORDER BY customer_name;

输出:

text
 customer_name
---------------
 Alice
 Bob
 Charlie

练习 5:理解差异 ​

答案:

两个查询结果相同,都返回不重复的客户名称:

sql
-- 使用 DISTINCT
SELECT DISTINCT customer_name FROM orders;

-- 使用 GROUP BY
SELECT customer_name FROM orders GROUP BY customer_name;

差异:

  • DISTINCT 专注于去重
  • GROUP BY 通常配合聚合函数使用,功能更强大

示例(GROUP BY 的优势):

sql
SELECT customer_name, COUNT(*) AS order_count
FROM orders
GROUP BY customer_name;

输出:

text
 customer_name | order_count
---------------+-------------
 Alice         |           3
 Bob           |           2
 Charlie       |           1

练习 6:DISTINCT ON(PostgreSQL) ​

答案:

sql
SELECT DISTINCT ON (customer_name) 
    customer_name, product, amount
FROM orders
ORDER BY customer_name, amount DESC;

输出:

text
 customer_name |  product | amount
---------------+----------+---------
 Alice         | Laptop   | 1200.00
 Bob           | Headphones|   50.00
 Charlie       | Monitor  |  300.00

这返回每个客户金额最大的订单。

练习 7:性能对比 ​

答案:

创建大表:

sql
CREATE TABLE large_orders AS 
SELECT 
    id,
    'Customer' || (id % 100) AS customer_name,
    'Product' || (id % 50) AS product
FROM generate_series(1, 10000) AS id;

比较性能:

sql
-- 无 DISTINCT
EXPLAIN ANALYZE SELECT customer_name FROM large_orders;

-- 有 DISTINCT
EXPLAIN ANALYZE SELECT DISTINCT customer_name FROM large_orders;

观察执行时间和操作(Sort 或 HashAggregate)。

练习 8:实际场景 ​

答案:

sql
SELECT DISTINCT customer_name 
FROM orders 
ORDER BY customer_name;

输出:

text
 customer_name
---------------
 Alice
 Bob
 Charlie

复习要点 ​

第一章关键概念 ​

  1. SELECT 结构:SELECT → FROM → WHERE → ORDER BY → LIMIT
  2. NULL 处理:使用 IS NULL / IS NOT NULL,不能用 = NULL
  3. 执行顺序:FROM → WHERE → SELECT → DISTINCT → ORDER BY → LIMIT
  4. 别名:WHERE 不能用别名,ORDER BY 可以
  5. DISTINCT:作用于所有选中的列,不是单列

常见陷阱 ​

  • ❌ WHERE age = NULL → ✅ WHERE age IS NULL
  • ❌ 字符串用双引号 → ✅ 字符串用单引号
  • ❌ 没有 ORDER BY 就用 LIMIT → ✅ 总是配合 ORDER BY
  • ❌ 以为 DISTINCT 只作用于第一列 → ✅ 作用于整行

返回第一章概览 · 返回SQL 学习路线

用心记录每一步成长