用 SELECT 把数据取出来看看
目标
直接连接 PostgreSQL,使用 SELECT、WHERE、DISTINCT、ORDER BY 筛选出所需的行,并能将结果保存为视图。
为什么重要
SQL 是声明式语言,而不是命令式语言。你不必写‘打开这个文件,逐行读取并比较’,只需写出‘给我满足这些条件的行’,数据库就会根据当时的统计信息决定如何查找。因此,写好 SQL 的关键是准确描述所需集合的能力,而不是掌握某种快速算法。
本实验尤其需要关注 NULL。NULL 与其说是‘没有值’,不如说是‘未知’,所以它与任何值比较都不会得到真。仅这一项性质就会影响查询、聚合和连接的方方面面,最好现在就亲手确认。
将查询保存为视图也有原因。视图不是复制一份结果,而是为查询本身命名,所以原始数据改变时,视图结果也会随之改变。评分脚本之所以能把你创建的视图与原始数据进行核对,正是利用了这一性质。
步骤
- 统计
customers表的总行数,只把数字保存到/root/rowcount.txt。 - 创建仅包含
is_active为真的客户的视图v_active_customers。保留原表全部列。 - 创建仅包含
country为KR且tier为gold的客户的视图v_kr_gold。 - 创建仅包含
email为空的客户的视图v_missing_email。 - 将
products的category无重复地保存到视图v_categories。视图只能包含category一列。 - 将
is_active为真且price大于等于 200000 的商品保存到视图v_expensive。 - 将
ordered_at晚于或等于TIMESTAMPTZ '2025-07-01 00:00:00+09'的订单保存到视图v_recent_orders。 - 将
country为KR且is_active为真的客户的id、name、tier依次保存到视图v_kr_report。先按tier升序排列,相同时再按id升序排列。
提示
- 连接:
psql -h 127.0.0.1 -U lab -d labdb(密码为lab,使用环境变量PGPASSWORD会更方便) - 可以用
\dt查看表列表,用\d customers查看列结构。 - 只把值输出到文件时,使用
psql -tAc "select ..." > 파일这种形式很方便。 - 常见错误 1:
WHERE email = NULL不会报错,只会返回 0 行。 - 常见错误 2:重新创建视图时可以使用
CREATE OR REPLACE VIEW,但如果列数或列名不同,就必须先执行DROP VIEW。
统计客户数量
统计 customers 表的总行数,只把数字保存到 /root/rowcount.txt。
将统计行数的聚合函数与只输出 psql 查询结果的选项(-t、-A)结合使用,就能让文件中只留下数字。
创建活跃客户视图
创建仅包含 is_active 为真的客户的视图 v_active_customers。保留原表全部列。
boolean 列可以直接用作条件,无需加上 = true。视图的形式为 CREATE VIEW 名称 AS SELECT ...。
同时应用两个条件
创建仅包含 country 为 KR 且 tier 为 gold 的客户的视图 v_kr_gold。
必须同时满足两个条件,因此使用 AND 连接。字符串比较区分大小写。
查找没有电子邮件的客户
创建仅包含 email 为空的客户的视图 v_missing_email。
NULL 与任何值比较都不会得到真。这里需要使用专用运算符,而不是等号。
提取类别列表
将 products 的 category 无重复地保存到视图 v_categories。视图只能包含 category 一列。
把用于去重的关键字放在 SELECT 后面。结果只能有一列,请勿加入其他列。
查找在售的高价商品
将 is_active 为真且 price 大于等于 200000 的商品保存到视图 v_expensive。
价格条件和在售条件必须同时应用。因为要求 20 万韩元以上,所以包含边界值。
筛选特定时间之后的订单
将 ordered_at 晚于或等于 TIMESTAMPTZ '2025-07-01 00:00:00+09' 的订单保存到视图 v_recent_orders。
ordered_at 是包含时区的类型。比较值也必须明确指定时区,才能不受服务器设置影响,始终得到相同结果。
用报表视图收尾
将 country 为 KR 且 is_active 为真的客户的 id、name、tier 依次保存到视图 v_kr_report。先按 tier 升序排列,相同时再按 id 升序排列。
只选择所需列,并正确设置别名。有两个排序条件时,在 ORDER BY 中用逗号依次列出。