PostgreSQL 别名(Aliases)
什么是别名?
别名是为表或列指定的临时名称,用于使查询更易读或更简洁。别名仅在查询执行期间存在。
列别名
基本语法
sql
SELECT column_name AS alias_name
FROM table_name;
-- 或省略AS关键字
SELECT column_name alias_name
FROM table_name;列别名示例
sql
-- 使用AS关键字
SELECT
first_name AS 名字,
last_name AS 姓氏,
email AS 电子邮件
FROM users;
-- 省略AS关键字
SELECT
first_name 名字,
last_name 姓氏,
email 电子邮件
FROM users;
-- 带空格的别名(使用引号)
SELECT
first_name AS "客户名字",
last_name AS "客户姓氏",
email AS "电子邮件地址"
FROM users;计算列的别名
sql
-- 算术运算
SELECT
product_name AS 产品名称,
price AS 原价,
price * 0.9 AS 折扣价,
price * 0.1 AS 节省金额
FROM products;
-- 字符串连接
SELECT
first_name || ' ' || last_name AS 全名,
UPPER(email) AS 大写邮箱
FROM users;
-- 聚合函数
SELECT
COUNT(*) AS 总用户数,
AVG(age) AS 平均年龄,
MAX(salary) AS 最高工资,
MIN(salary) AS 最低工资
FROM employees;使用函数的别名
sql
-- 日期函数
SELECT
order_date AS 订单日期,
EXTRACT(YEAR FROM order_date) AS 年份,
EXTRACT(MONTH FROM order_date) AS 月份,
AGE(order_date) AS 距今时间
FROM orders;
-- 字符串函数
SELECT
name AS 原始名称,
UPPER(name) AS 大写名称,
LOWER(name) AS 小写名称,
LENGTH(name) AS 名称长度
FROM products;表别名
基本语法
sql
SELECT alias.column_name
FROM table_name AS alias;
-- 或省略AS关键字
SELECT alias.column_name
FROM table_name alias;表别名示例
sql
-- 简单表别名
SELECT
u.id,
u.name,
u.email
FROM users AS u;
-- 省略AS关键字
SELECT
u.id,
u.name,
u.email
FROM users u;
-- 多表查询中的别名
SELECT
u.name AS 用户名,
o.order_number AS 订单号,
o.total AS 订单金额
FROM users u
INNER JOIN orders o ON u.id = o.user_id;复杂查询中的表别名
sql
-- 三表连接
SELECT
c.name AS 客户名称,
o.order_number AS 订单号,
p.product_name AS 产品名称,
oi.quantity AS 数量,
oi.price AS 单价
FROM customers c
INNER JOIN orders o ON c.id = o.customer_id
INNER JOIN order_items oi ON o.id = oi.order_id
INNER JOIN products p ON oi.product_id = p.id;
-- 自连接(必须使用别名)
SELECT
e1.name AS 员工,
e2.name AS 经理
FROM employees e1
LEFT JOIN employees e2 ON e1.manager_id = e2.id;子查询中的别名
派生表别名
sql
-- 子查询必须有别名
SELECT
dept_stats.department,
dept_stats.avg_salary,
dept_stats.employee_count
FROM (
SELECT
department,
AVG(salary) AS avg_salary,
COUNT(*) AS employee_count
FROM employees
GROUP BY department
) AS dept_stats
WHERE dept_stats.avg_salary > 50000;CTE(公用表表达式)别名
sql
-- WITH子句中的别名
WITH high_value_customers AS (
SELECT
customer_id,
SUM(total) AS total_spent
FROM orders
GROUP BY customer_id
HAVING SUM(total) > 10000
)
SELECT
c.name AS 客户名称,
hvc.total_spent AS 总消费
FROM high_value_customers hvc
INNER JOIN customers c ON hvc.customer_id = c.id;在不同子句中使用别名
WHERE 子句
sql
-- 注意:不能在WHERE中直接使用列别名
-- 错误示例
SELECT
price * quantity AS total
FROM order_items
WHERE total > 100; -- 错误!
-- 正确方法:重复表达式
SELECT
price * quantity AS total
FROM order_items
WHERE price * quantity > 100;
-- 或使用子查询
SELECT * FROM (
SELECT
price * quantity AS total
FROM order_items
) AS items
WHERE total > 100;ORDER BY 子句
sql
-- 可以在ORDER BY中使用列别名
SELECT
first_name || ' ' || last_name AS full_name,
salary * 12 AS annual_salary
FROM employees
ORDER BY annual_salary DESC;
-- 也可以使用列位置
SELECT
first_name || ' ' || last_name AS full_name,
salary * 12 AS annual_salary
FROM employees
ORDER BY 2 DESC; -- 按第2列排序GROUP BY 子句
sql
-- 不能在GROUP BY中直接使用列别名
-- 错误示例
SELECT
EXTRACT(YEAR FROM order_date) AS year,
COUNT(*) AS order_count
FROM orders
GROUP BY year; -- 错误!
-- 正确方法:重复表达式
SELECT
EXTRACT(YEAR FROM order_date) AS year,
COUNT(*) AS order_count
FROM orders
GROUP BY EXTRACT(YEAR FROM order_date);
-- PostgreSQL特有:可以使用列位置
SELECT
EXTRACT(YEAR FROM order_date) AS year,
COUNT(*) AS order_count
FROM orders
GROUP BY 1;HAVING 子句
sql
-- 可以在HAVING中使用聚合别名(PostgreSQL扩展)
SELECT
department,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING avg_salary > 50000; -- PostgreSQL允许
-- 标准SQL方法(更兼容)
SELECT
department,
AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 50000;实际应用场景
场景 1:报表生成
sql
SELECT
p.product_name AS "产品名称",
c.category_name AS "类别",
COUNT(oi.id) AS "销售次数",
SUM(oi.quantity) AS "总销量",
SUM(oi.quantity * oi.price) AS "总销售额",
AVG(oi.price) AS "平均单价"
FROM products p
INNER JOIN categories c ON p.category_id = c.id
LEFT JOIN order_items oi ON p.id = oi.product_id
GROUP BY p.id, p.product_name, c.category_name
ORDER BY "总销售额" DESC;场景 2:数据分析
sql
SELECT
DATE_TRUNC('month', order_date) AS 月份,
COUNT(DISTINCT customer_id) AS 活跃客户数,
COUNT(*) AS 订单总数,
SUM(total) AS 月度收入,
AVG(total) AS 平均订单金额
FROM orders
WHERE order_date >= CURRENT_DATE - INTERVAL '1 year'
GROUP BY 月份
ORDER BY 月份 DESC;场景 3:复杂计算
sql
SELECT
e.name AS 员工姓名,
e.salary AS 基本工资,
e.salary * 0.1 AS 奖金,
e.salary * 1.1 AS 总收入,
d.name AS 部门名称,
(
SELECT AVG(salary)
FROM employees
WHERE department_id = e.department_id
) AS 部门平均工资,
e.salary - (
SELECT AVG(salary)
FROM employees
WHERE department_id = e.department_id
) AS 与平均工资差额
FROM employees e
INNER JOIN departments d ON e.department_id = d.id;别名命名规范
好的实践
sql
-- 使用有意义的名称
SELECT
customer_id AS cust_id,
first_name AS fname,
last_name AS lname
FROM customers;
-- 表别名使用简短但清晰的名称
SELECT
c.name,
o.order_number,
p.product_name
FROM customers c
INNER JOIN orders o ON c.id = o.customer_id
INNER JOIN order_items oi ON o.id = oi.order_id
INNER JOIN products p ON oi.product_id = p.id;避免的做法
sql
-- 避免:过于简短,不清晰
SELECT
a.x,
b.y
FROM table1 a
INNER JOIN table2 b ON a.id = b.id;
-- 避免:使用保留字
SELECT
name AS select, -- 不好
price AS from -- 不好
FROM products;
-- 避免:过长的别名
SELECT
name AS this_is_a_very_long_and_unnecessary_alias_name
FROM products;特殊情况
带引号的别名
sql
-- 需要引号的情况:
-- 1. 包含空格
SELECT name AS "Product Name" FROM products;
-- 2. 包含特殊字符
SELECT price AS "Price ($)" FROM products;
-- 3. 保留关键字
SELECT status AS "Order" FROM orders;
-- 4. 区分大小写(PostgreSQL默认不区分)
SELECT name AS "ProductName" FROM products;数字别名
sql
-- 可以使用数字开头(需要引号)
SELECT
name AS "1st_name",
email AS "2nd_email"
FROM users;性能考虑
别名本身不影响查询性能,但可以:
- 提高可读性:使复杂查询更易理解
- 简化维护:更改表名时只需修改别名定义
- 避免歧义:在多表连接中明确列来源
sql
-- 使用EXPLAIN查看执行计划
EXPLAIN ANALYZE
SELECT
u.name AS user_name,
COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name;最佳实践
列别名:
- 使用AS关键字提高可读性
- 为计算列提供有意义的名称
- 报表中使用描述性别名
表别名:
- 多表查询中始终使用表别名
- 使用简短但清晰的别名
- 自连接必须使用别名
命名约定:
- 使用小写和下划线
- 避免保留关键字
- 保持一致的命名风格
可读性:
- 复杂查询中使用别名提高可读性
- 在JOIN条件中明确使用表别名
- 为子查询提供有意义的别名
小结
别名是 SQL 查询的重要工具:
- 列别名:为列或表达式提供临时名称
- 表别名:简化表引用,特别是在JOIN中
- AS关键字:可选但推荐使用
- 引号:包含空格或特殊字符时需要
- 作用域:仅在查询执行期间有效
- 限制:某些子句中不能直接使用别名
掌握别名的使用可以使 SQL 查询更清晰、更易维护。