Initial commit of akmon project

This commit is contained in:
2026-01-20 08:04:15 +08:00
commit 77a2bab985
1309 changed files with 343305 additions and 0 deletions

212
AMBIGUOUS_COLUMN_FIX.md Normal file
View File

@@ -0,0 +1,212 @@
# 列引用歧义修复说明
## 问题描述
在执行 `video_system_database.sql` 时,遇到了 `ERROR: 42702: column reference "user_id" is ambiguous` 错误。这表明在 SQL 查询中存在列名歧义,即多个表都有相同的列名,但没有明确指定使用哪个表的列。
## 错误位置
错误发生在 `vw_user_media_stats` 视图的定义中(大约第 565 行):
```sql
-- 有问题的代码
SELECT
user_id, -- 歧义ui.user_id 还是 vpr.user_id
...
FROM ak_user_interactions ui
LEFT JOIN ak_contents c ON ui.content_id = c.id
LEFT JOIN ak_video_play_records vpr ON ui.content_id = vpr.content_id AND ui.user_id = vpr.user_id
WHERE ui.interaction_type = 'view'
GROUP BY user_id; -- 歧义ui.user_id 还是 vpr.user_id
```
## 根本原因
当在 SQL 查询中联接多个表时,如果这些表包含相同名称的列,必须使用表别名来明确指定要引用的是哪个表的列。
在这个视图中:
- `ak_user_interactions` 表有 `user_id`
- `ak_video_play_records` 表也有 `user_id`
当我们在 SELECT 子句中写 `user_id`PostgreSQL 不知道我们指的是哪个表的 `user_id`,因此报告列引用歧义错误。
## 修复方案
### 1. 使用表别名明确指定列
**修复前(有问题的代码)**
```sql
SELECT
user_id, -- 歧义
...
FROM ak_user_interactions ui
LEFT JOIN ak_video_play_records vpr ON ...
GROUP BY user_id; -- 歧义
```
**修复后(正确的代码)**
```sql
SELECT
ui.user_id, -- 明确指定来自 ak_user_interactions 表
...
FROM ak_user_interactions ui
LEFT JOIN ak_video_play_records vpr ON ...
GROUP BY ui.user_id; -- 明确指定来自 ak_user_interactions 表
```
### 2. 完整的修复代码
```sql
CREATE OR REPLACE VIEW vw_user_media_stats AS
SELECT
ui.user_id, -- 明确指定表别名
COUNT(CASE WHEN c.content_type = 'video' THEN 1 END) as videos_watched,
COUNT(CASE WHEN c.content_type = 'audio' THEN 1 END) as audios_listened,
COUNT(CASE WHEN c.content_type = 'image' THEN 1 END) as images_viewed,
SUM(CASE WHEN c.content_type IN ('video', 'audio') THEN vpr.play_duration ELSE 0 END) as total_play_time,
AVG(CASE WHEN c.content_type IN ('video', 'audio') THEN vpr.play_percentage ELSE NULL END) as avg_completion_rate
FROM ak_user_interactions ui
LEFT JOIN ak_contents c ON ui.content_id = c.id
LEFT JOIN ak_video_play_records vpr ON ui.content_id = vpr.content_id AND ui.user_id = vpr.user_id
WHERE ui.interaction_type = 'view'
GROUP BY ui.user_id; -- 明确指定表别名
```
## 最佳实践
### 1. 始终使用表别名
```sql
-- ✅ 推荐:使用表别名
SELECT
u.user_id,
u.user_name,
p.profile_data
FROM users u
JOIN profiles p ON u.id = p.user_id;
-- ❌ 避免:不使用表别名(可能产生歧义)
SELECT
user_id, -- 如果两个表都有这个列,会报错
user_name,
profile_data
FROM users
JOIN profiles ON users.id = profiles.user_id;
```
### 2. 有意义的表别名
```sql
-- ✅ 推荐:有意义的别名
FROM ak_user_interactions ui
LEFT JOIN ak_contents c
LEFT JOIN ak_video_play_records vpr
-- ❌ 避免:无意义的别名
FROM ak_user_interactions a
LEFT JOIN ak_contents b
LEFT JOIN ak_video_play_records c
```
### 3. 一致的命名约定
```sql
-- ✅ 推荐:一致的命名
FROM ak_user_interactions ui
FROM ak_content_comments cc
FROM ak_video_danmakus vd
-- ❌ 避免:不一致的命名
FROM ak_user_interactions interactions
FROM ak_content_comments c
FROM ak_video_danmakus danmu
```
## 验证方法
### 测试修复
```sql
-- 测试视图是否可以正常创建
CREATE OR REPLACE VIEW vw_user_media_stats AS ...;
-- 测试视图是否可以正常查询
SELECT * FROM vw_user_media_stats LIMIT 5;
-- 检查返回的列是否正确
\d vw_user_media_stats
```
### 查找潜在的歧义
```sql
-- 检查是否有其他可能的列名歧义
SELECT
table_name,
column_name,
COUNT(*) as table_count
FROM information_schema.columns
WHERE table_schema = current_schema()
AND table_name LIKE 'ak_%'
GROUP BY column_name
HAVING COUNT(*) > 1
ORDER BY table_count DESC, column_name;
```
## 其他常见的歧义情况
### 1. ID 列歧义
```sql
-- 可能有歧义的查询
SELECT id FROM table1 t1 JOIN table2 t2 ON t1.ref_id = t2.id;
-- 修复:明确指定表
SELECT t1.id FROM table1 t1 JOIN table2 t2 ON t1.ref_id = t2.id;
```
### 2. 时间戳列歧义
```sql
-- 可能有歧义
SELECT created_at FROM posts p JOIN comments c ON p.id = c.post_id;
-- 修复:明确指定表
SELECT p.created_at FROM posts p JOIN comments c ON p.id = c.post_id;
```
### 3. 状态列歧义
```sql
-- 可能有歧义
SELECT status FROM orders o JOIN payments p ON o.id = p.order_id;
-- 修复:明确指定表或使用别名
SELECT
o.status as order_status,
p.status as payment_status
FROM orders o
JOIN payments p ON o.id = p.order_id;
```
## 预防措施
### 1. 代码审查清单
在创建包含多表 JOIN 的查询时,检查:
- ✅ 所有列都有明确的表别名
- ✅ 表别名有意义且一致
- ✅ GROUP BY 子句中的列也有表别名
- ✅ ORDER BY 子句中的列也有表别名
### 2. 开发工具配置
使用支持 SQL 语法检查的编辑器,可以在开发时发现潜在的歧义。
### 3. 测试策略
- 在开发环境中测试所有视图
- 使用自动化测试验证 SQL 语法
- 定期检查数据库结构变更对现有查询的影响
修复后的数据库现在可以正常部署,所有列引用都是明确无歧义的。