534 lines
17 KiB
PL/PgSQL
534 lines
17 KiB
PL/PgSQL
-- ===========================================
|
|
-- 高中数学知识图谱常用查询视图和函数
|
|
-- ===========================================
|
|
|
|
-- ===========================================
|
|
-- 1. 知识图谱查询视图
|
|
-- ===========================================
|
|
|
|
-- 知识点详细信息视图(已创建,这里重新定义以包含更多信息)
|
|
CREATE OR REPLACE VIEW knowledge_detail_view AS
|
|
SELECT
|
|
kp.id,
|
|
kp.code,
|
|
kp.name,
|
|
kp.level,
|
|
kp.type,
|
|
kp.importance,
|
|
kp.core_content,
|
|
kp.principle_explanation,
|
|
kp.examination_methods,
|
|
kp.textbook_location,
|
|
s.section_name,
|
|
c.chapter_name,
|
|
t.name as textbook_name,
|
|
t.volume_type,
|
|
t.volume_number,
|
|
-- 前置知识点数量
|
|
(SELECT COUNT(*) FROM knowledge_relations kr
|
|
WHERE kr.target_knowledge_id = kp.id AND kr.relation_type = '前置知识') as prerequisite_count,
|
|
-- 支撑的方法数量
|
|
(SELECT COUNT(*) FROM method_support_knowledge msk
|
|
WHERE msk.knowledge_id = kp.id) as supported_methods_count,
|
|
-- 考查的题目数量
|
|
(SELECT COUNT(*) FROM problem_knowledge_tags pkt
|
|
WHERE pkt.knowledge_id = kp.id AND pkt.tag_type = '主要考查') as problem_count,
|
|
kp.created_at,
|
|
kp.updated_at
|
|
FROM knowledge_points kp
|
|
LEFT JOIN sections s ON kp.section_id = s.id
|
|
LEFT JOIN chapters c ON s.chapter_id = c.id
|
|
LEFT JOIN textbooks t ON c.textbook_id = t.id;
|
|
|
|
-- 方法详细信息视图
|
|
CREATE OR REPLACE VIEW method_detail_view AS
|
|
SELECT
|
|
m.id,
|
|
m.code,
|
|
m.name,
|
|
m.type,
|
|
m.difficulty_level,
|
|
m.mathematical_thoughts,
|
|
m.problem_solving_strategy,
|
|
m.textbook_location,
|
|
m.description,
|
|
s.section_name,
|
|
c.chapter_name,
|
|
t.name as textbook_name,
|
|
t.volume_type,
|
|
-- 支撑的知识点数量
|
|
(SELECT COUNT(*) FROM method_support_knowledge msk WHERE msk.method_id = m.id) as support_knowledge_count,
|
|
-- 步骤数量
|
|
(SELECT COUNT(*) FROM method_steps ms WHERE ms.method_id = m.id) as step_count,
|
|
-- 常见错误数量
|
|
(SELECT COUNT(*) FROM method_common_errors mce WHERE mce.method_id = m.id) as error_count,
|
|
-- 使用的题目数量
|
|
(SELECT COUNT(*) FROM problem_method_tags pmt WHERE pmt.method_id = m.id) as usage_count,
|
|
m.created_at,
|
|
m.updated_at
|
|
FROM methods m
|
|
LEFT JOIN sections s ON m.section_id = s.id
|
|
LEFT JOIN chapters c ON s.chapter_id = c.id
|
|
LEFT JOIN textbooks t ON c.textbook_id = t.id;
|
|
|
|
-- 题目详细信息视图
|
|
CREATE OR REPLACE VIEW problem_detail_view AS
|
|
SELECT
|
|
p.id,
|
|
p.code,
|
|
p.problem_type,
|
|
p.title,
|
|
p.stem,
|
|
p.full_content,
|
|
p.subquestion_count,
|
|
p.difficulty_info,
|
|
p.textbook_location,
|
|
s.section_name,
|
|
c.chapter_name,
|
|
t.name as textbook_name,
|
|
t.volume_type,
|
|
-- 涉及的知识点数量
|
|
(SELECT COUNT(DISTINCT pkt.knowledge_id) FROM problem_knowledge_tags pkt
|
|
WHERE pkt.problem_id = p.id) as knowledge_count,
|
|
-- 使用的方法数量
|
|
(SELECT COUNT(DISTINCT pmt.method_id) FROM problem_method_tags pmt
|
|
WHERE pmt.problem_id = p.id) as method_count,
|
|
p.created_at,
|
|
p.updated_at
|
|
FROM problems p
|
|
LEFT JOIN knowledge_points kp ON p.section_id = kp.section_id
|
|
LEFT JOIN sections s ON kp.section_id = s.id
|
|
LEFT JOIN chapters c ON s.chapter_id = c.id
|
|
LEFT JOIN textbooks t ON c.textbook_id = t.id;
|
|
|
|
-- 知识点关系网络视图
|
|
CREATE OR REPLACE VIEW knowledge_relation_network AS
|
|
SELECT
|
|
kp1.code as source_code,
|
|
kp1.name as source_name,
|
|
kp2.code as target_code,
|
|
kp2.name as target_name,
|
|
kr.relation_type,
|
|
kr.strength,
|
|
kr.description
|
|
FROM knowledge_relations kr
|
|
JOIN knowledge_points kp1 ON kr.source_knowledge_id = kp1.id
|
|
JOIN knowledge_points kp2 ON kr.target_knowledge_id = kp2.id;
|
|
|
|
-- ===========================================
|
|
-- 2. 统计分析视图
|
|
-- ===========================================
|
|
|
|
-- 章节知识密度统计视图
|
|
CREATE OR REPLACE VIEW chapter_knowledge_density AS
|
|
SELECT
|
|
c.id,
|
|
c.chapter_name,
|
|
c.chapter_number,
|
|
t.name as textbook_name,
|
|
COUNT(DISTINCT kp.id) as knowledge_count,
|
|
COUNT(DISTINCT m.id) as method_count,
|
|
COUNT(DISTINCT p.id) as problem_count,
|
|
-- 核心知识点数量
|
|
COUNT(DISTINCT CASE WHEN kp.importance = '核心' THEN kp.id END) as core_knowledge_count,
|
|
-- 平均难度
|
|
COALESCE(AVG(p.difficulty_info->>'整体难度')::float, 0) as avg_problem_difficulty,
|
|
-- 知识点密度(知识点数量/题目数量)
|
|
CASE WHEN COUNT(DISTINCT p.id) > 0
|
|
THEN ROUND(COUNT(DISTINCT kp.id)::float / COUNT(DISTINCT p.id), 2)
|
|
ELSE 0 END as knowledge_density
|
|
FROM chapters c
|
|
LEFT JOIN sections s ON c.id = s.chapter_id
|
|
LEFT JOIN knowledge_points kp ON s.id = kp.section_id
|
|
LEFT JOIN methods m ON s.id = m.section_id
|
|
LEFT JOIN problem_knowledge_tags pkt ON kp.id = pkt.knowledge_id
|
|
LEFT JOIN problems p ON pkt.problem_id = p.id
|
|
LEFT JOIN textbooks t ON c.textbook_id = t.id
|
|
GROUP BY c.id, c.chapter_name, c.chapter_number, t.name
|
|
ORDER BY c.chapter_number;
|
|
|
|
-- 知识点考查频次统计视图
|
|
CREATE OR REPLACE VIEW knowledge_examination_frequency AS
|
|
SELECT
|
|
kp.code,
|
|
kp.name,
|
|
kp.level,
|
|
kp.importance,
|
|
COUNT(pkt.id) as total_references,
|
|
COUNT(DISTINCT CASE WHEN pkt.tag_type = '主要考查' THEN pkt.problem_id END) as main_problems,
|
|
COUNT(DISTINCT CASE WHEN pkt.tag_type = '辅助涉及' THEN pkt.problem_id END) as auxiliary_problems,
|
|
-- 平均题目难度
|
|
COALESCE(AVG(p.difficulty_info->>'整体难度')::float, 0) as avg_problem_difficulty,
|
|
-- 考查类型分布
|
|
STRING_AGG(DISTINCT p.problem_type, ', ') as problem_types
|
|
FROM knowledge_points kp
|
|
LEFT JOIN problem_knowledge_tags pkt ON kp.id = pkt.knowledge_id
|
|
LEFT JOIN problems p ON pkt.problem_id = p.id
|
|
GROUP BY kp.id, kp.code, kp.name, kp.level, kp.importance
|
|
HAVING COUNT(pkt.id) > 0
|
|
ORDER BY total_references DESC;
|
|
|
|
-- 方法使用频次统计视图
|
|
CREATE OR REPLACE VIEW method_usage_frequency AS
|
|
SELECT
|
|
m.code,
|
|
m.name,
|
|
m.type,
|
|
m.difficulty_level,
|
|
COUNT(pmt.id) as total_usage,
|
|
COUNT(DISTINCT pmt.problem_id) as used_in_problems,
|
|
-- 方法类型分布
|
|
STRING_AGG(DISTINCT p.problem_type, ', ') as problem_types,
|
|
-- 平均题目难度
|
|
COALESCE(AVG(p.difficulty_info->>'整体难度')::float, 0) as avg_problem_difficulty
|
|
FROM methods m
|
|
LEFT JOIN problem_method_tags pmt ON m.id = pmt.method_id
|
|
LEFT JOIN problems p ON pmt.problem_id = p.id
|
|
GROUP BY m.id, m.code, m.name, m.type, m.difficulty_level
|
|
HAVING COUNT(pmt.id) > 0
|
|
ORDER BY total_usage DESC;
|
|
|
|
-- ===========================================
|
|
-- 3. 学习路径和推荐视图
|
|
-- ===========================================
|
|
|
|
-- 核心知识点学习路径视图
|
|
CREATE OR REPLACE VIEW core_learning_path AS
|
|
WITH RECURSIVE learning_sequence AS (
|
|
-- 基础层:无前置知识的核心知识点
|
|
SELECT
|
|
kp.id,
|
|
kp.code,
|
|
kp.name,
|
|
kp.level,
|
|
kp.importance,
|
|
1 as sequence_level,
|
|
ARRAY[kp.id] as prerequisite_path,
|
|
kp.textbook_location
|
|
FROM knowledge_points kp
|
|
WHERE kp.importance = '核心'
|
|
AND NOT EXISTS (
|
|
SELECT 1 FROM knowledge_relations kr
|
|
WHERE kr.target_knowledge_id = kp.id
|
|
AND kr.relation_type = '前置知识'
|
|
)
|
|
|
|
UNION ALL
|
|
|
|
-- 递归:基于前置知识查找下一层知识点
|
|
SELECT
|
|
kp.id,
|
|
kp.code,
|
|
kp.name,
|
|
kp.level,
|
|
kp.importance,
|
|
ls.sequence_level + 1 as sequence_level,
|
|
ls.prerequisite_path || kp.id as prerequisite_path,
|
|
kp.textbook_location
|
|
FROM knowledge_points kp
|
|
JOIN knowledge_relations kr ON kp.id = kr.source_knowledge_id
|
|
JOIN learning_sequence ls ON kr.target_knowledge_id = ls.id
|
|
WHERE kr.relation_type = '前置知识'
|
|
AND kp.importance IN ('核心', '重要')
|
|
AND kp.id != ALL(ls.prerequisite_path)
|
|
AND ls.sequence_level < 5
|
|
)
|
|
SELECT
|
|
code,
|
|
name,
|
|
level,
|
|
importance,
|
|
sequence_level,
|
|
textbook_location,
|
|
-- 前置知识点数量
|
|
sequence_level - 1 as prerequisite_count
|
|
FROM learning_sequence
|
|
ORDER BY sequence_level, code;
|
|
|
|
-- 易错点分析视图
|
|
CREATE OR REPLACE VIEW error_prone_analysis AS
|
|
SELECT
|
|
m.code as method_code,
|
|
m.name as method_name,
|
|
m.difficulty_level,
|
|
COUNT(mce.id) as error_count,
|
|
-- 错误类型汇总
|
|
STRING_AGG(DISTINCT LEFT(mce.error_description, 30), '; ') as error_types,
|
|
-- 使用该方法的题目平均难度
|
|
COALESCE(AVG(p.difficulty_info->>'整体难度')::float, m.difficulty_level::float) as avg_usage_difficulty
|
|
FROM methods m
|
|
LEFT JOIN method_common_errors mce ON m.id = mce.method_id
|
|
LEFT JOIN problem_method_tags pmt ON m.id = pmt.method_id
|
|
LEFT JOIN problems p ON pmt.problem_id = p.id
|
|
GROUP BY m.id, m.code, m.name, m.difficulty_level
|
|
HAVING COUNT(mce.id) > 0
|
|
ORDER BY error_count DESC, avg_usage_difficulty DESC;
|
|
|
|
-- ===========================================
|
|
-- 4. 实用查询函数
|
|
-- ===========================================
|
|
|
|
-- 获取知识点的完整前置链
|
|
CREATE OR REPLACE FUNCTION get_knowledge_prerequisite_chain(knowledge_code VARCHAR)
|
|
RETURNS TABLE (
|
|
level INTEGER,
|
|
code VARCHAR,
|
|
name VARCHAR,
|
|
prerequisite_for VARCHAR
|
|
) AS $$
|
|
WITH RECURSIVE prerequisite_chain AS (
|
|
-- 起始知识点
|
|
SELECT
|
|
0 as level,
|
|
kp.code,
|
|
kp.name,
|
|
NULL::VARCHAR as prerequisite_for
|
|
FROM knowledge_points kp
|
|
WHERE kp.code = knowledge_code
|
|
|
|
UNION ALL
|
|
|
|
-- 递归查找前置知识点
|
|
SELECT
|
|
pc.level + 1,
|
|
kp.code,
|
|
kp.name,
|
|
pc.code as prerequisite_for
|
|
FROM prerequisite_chain pc
|
|
JOIN knowledge_relations kr ON kr.source_knowledge_id = (
|
|
SELECT id FROM knowledge_points WHERE code = pc.code
|
|
)
|
|
JOIN knowledge_points kp ON kr.target_knowledge_id = kp.id
|
|
WHERE kr.relation_type = '前置知识'
|
|
AND pc.level < 10 -- 防止无限递归
|
|
)
|
|
SELECT level, code, name, prerequisite_for
|
|
FROM prerequisite_chain
|
|
WHERE level > 0 -- 排除起始知识点
|
|
ORDER BY level;
|
|
$$ LANGUAGE SQL;
|
|
|
|
-- 获取知识点相关的题目推荐
|
|
CREATE OR REPLACE FUNCTION get_problem_recommendations(knowledge_code VARCHAR, limit_count INTEGER DEFAULT 5)
|
|
RETURNS TABLE (
|
|
problem_code VARCHAR,
|
|
problem_type VARCHAR,
|
|
difficulty_level FLOAT,
|
|
title TEXT,
|
|
relevance_score FLOAT
|
|
) AS $$
|
|
SELECT
|
|
p.code,
|
|
p.problem_type,
|
|
(p.difficulty_info->>'整体难度')::float as difficulty_level,
|
|
p.title,
|
|
-- 相关性评分:基于知识点标注类型
|
|
CASE
|
|
WHEN pkt.tag_type = '主要考查' THEN 1.0
|
|
WHEN pkt.tag_type = '辅助涉及' THEN 0.5
|
|
ELSE 0.1
|
|
END as relevance_score
|
|
FROM problems p
|
|
JOIN problem_knowledge_tags pkt ON p.id = pkt.problem_id
|
|
JOIN knowledge_points kp ON pkt.knowledge_id = kp.id
|
|
WHERE kp.code = knowledge_code
|
|
ORDER BY relevance_score DESC, difficulty_level ASC
|
|
LIMIT limit_count;
|
|
$$ LANGUAGE SQL;
|
|
|
|
-- 搜索相关内容(全文搜索)
|
|
CREATE OR REPLACE FUNCTION search_knowledge_content(search_term TEXT, content_type VARCHAR DEFAULT 'all')
|
|
RETURNS TABLE (
|
|
type VARCHAR,
|
|
code VARCHAR,
|
|
name VARCHAR,
|
|
snippet TEXT,
|
|
relevance_score FLOAT
|
|
) AS $$
|
|
BEGIN
|
|
RETURN QUERY
|
|
-- 搜索知识点
|
|
SELECT
|
|
'knowledge' as type,
|
|
kp.code,
|
|
kp.name,
|
|
ts_headline('chinese', kp.name, to_tsquery('chinese', search_term)) as snippet,
|
|
ts_rank(kp.search_vector, to_tsquery('chinese', search_term)) as relevance_score
|
|
FROM knowledge_points kp
|
|
WHERE kp.search_vector @@ to_tsquery('chinese', search_term)
|
|
|
|
UNION ALL
|
|
|
|
-- 搜索方法
|
|
SELECT
|
|
'method' as type,
|
|
m.code,
|
|
m.name,
|
|
ts_headline('chinese', m.name, to_tsquery('chinese', search_term)) as snippet,
|
|
ts_rank(m.search_vector, to_tsquery('chinese', search_term)) as relevance_score
|
|
FROM methods m
|
|
WHERE m.search_vector @@ to_tsquery('chinese', search_term)
|
|
|
|
UNION ALL
|
|
|
|
-- 搜索题目
|
|
SELECT
|
|
'problem' as type,
|
|
p.code,
|
|
COALESCE(p.title, '无标题') as name,
|
|
ts_headline('chinese', p.stem, to_tsquery('chinese', search_term)) as snippet,
|
|
ts_rank(p.search_vector, to_tsquery('chinese', search_term)) as relevance_score
|
|
FROM problems p
|
|
WHERE p.search_vector @@ to_tsquery('chinese', search_term)
|
|
|
|
ORDER BY relevance_score DESC;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- 计算知识点掌握度评估
|
|
CREATE OR REPLACE FUNCTION evaluate_knowledge_mastery(student_id INTEGER, knowledge_code VARCHAR)
|
|
RETURNS TABLE (
|
|
knowledge_code VARCHAR,
|
|
mastery_level NUMERIC,
|
|
recommended_actions TEXT[]
|
|
) AS $$
|
|
BEGIN
|
|
RETURN QUERY
|
|
WITH problem_performance AS (
|
|
SELECT
|
|
kp.code,
|
|
-- 这里需要实际的答题记录表来计算掌握度
|
|
-- 暂时使用题目难度作为反向指标
|
|
CASE
|
|
WHEN COUNT(pkt.id) = 0 THEN 0.0
|
|
ELSE LEAST(1.0, 1.0 - AVG((p.difficulty_info->>'整体难度')::float) / 5.0)
|
|
END as mastery_level
|
|
FROM knowledge_points kp
|
|
LEFT JOIN problem_knowledge_tags pkt ON kp.id = pkt.knowledge_id
|
|
LEFT JOIN problems p ON pkt.problem_id = p.id
|
|
WHERE kp.code = knowledge_code
|
|
GROUP BY kp.code
|
|
)
|
|
SELECT
|
|
pp.code,
|
|
pp.mastery_level,
|
|
CASE
|
|
WHEN pp.mastery_level >= 0.8 THEN ARRAY['巩固练习', '挑战难题']
|
|
WHEN pp.mastery_level >= 0.6 THEN ARRAY['加强基础练习', '重点复习']
|
|
WHEN pp.mastery_level >= 0.4 THEN ARRAY['返回基础', '系统学习']
|
|
ELSE ARRAY['从基础开始', '寻求辅导']
|
|
END as recommended_actions
|
|
FROM problem_performance pp;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- ===========================================
|
|
-- 5. 数据质量检查视图
|
|
-- ===========================================
|
|
|
|
-- 孤立知识点检查(无前置关系和后继关系)
|
|
CREATE OR REPLACE VIEW orphaned_knowledge_points AS
|
|
SELECT
|
|
kp.code,
|
|
kp.name,
|
|
kp.level,
|
|
kp.importance,
|
|
'无关联关系' as issue_type
|
|
FROM knowledge_points kp
|
|
LEFT JOIN knowledge_relations kr_out ON kp.id = kr_out.source_knowledge_id
|
|
LEFT JOIN knowledge_relations kr_in ON kp.id = kr_in.target_knowledge_id
|
|
WHERE kr_out.source_knowledge_id IS NULL
|
|
AND kr_in.target_knowledge_id IS NULL
|
|
AND kp.importance = '核心';
|
|
|
|
-- 缺失标注检查
|
|
CREATE OR REPLACE VIEW missing_tags_check AS
|
|
SELECT
|
|
'problems_without_knowledge_tags' as check_type,
|
|
COUNT(*) as count,
|
|
'缺少知识点标注的题目' as description
|
|
FROM problems p
|
|
WHERE NOT EXISTS (
|
|
SELECT 1 FROM problem_knowledge_tags pkt WHERE pkt.problem_id = p.id
|
|
)
|
|
|
|
UNION ALL
|
|
|
|
SELECT
|
|
'problems_without_method_tags' as check_type,
|
|
COUNT(*) as count,
|
|
'缺少方法标注的题目' as description
|
|
FROM problems p
|
|
WHERE NOT EXISTS (
|
|
SELECT 1 FROM problem_method_tags pmt WHERE pmt.problem_id = p.id
|
|
)
|
|
|
|
UNION ALL
|
|
|
|
SELECT
|
|
'methods_without_knowledge_support' as check_type,
|
|
COUNT(*) as count,
|
|
'缺少支撑知识点的方法' as description
|
|
FROM methods m
|
|
WHERE NOT EXISTS (
|
|
SELECT 1 FROM method_support_knowledge msk WHERE msk.method_id = m.id
|
|
);
|
|
|
|
-- 编号格式一致性检查
|
|
CREATE OR REPLACE VIEW code_format_consistency AS
|
|
SELECT
|
|
'knowledge_code_format' as check_type,
|
|
COUNT(*) as invalid_count,
|
|
'知识点编号格式不正确' as description
|
|
FROM knowledge_points kp
|
|
WHERE kp.code !~ '^K\d+-\d+-\d+-\d+$'
|
|
|
|
UNION ALL
|
|
|
|
SELECT
|
|
'method_code_format' as check_type,
|
|
COUNT(*) as invalid_count,
|
|
'方法编号格式不正确' as description
|
|
FROM methods m
|
|
WHERE m.code !~ '^M\d+-\d+-\d+-\d+$'
|
|
|
|
UNION ALL
|
|
|
|
SELECT
|
|
'problem_code_format' as check_type,
|
|
COUNT(*) as invalid_count,
|
|
'题目编号格式不正确' as description
|
|
FROM problems p
|
|
WHERE p.code !~ '^T\d+-\d+-\d+-[A-Z]\d+$';
|
|
|
|
-- ===========================================
|
|
-- 6. 使用示例
|
|
-- ===========================================
|
|
|
|
/*
|
|
-- 基础查询示例
|
|
SELECT * FROM knowledge_detail_view WHERE importance = '核心' LIMIT 10;
|
|
SELECT * FROM method_detail_view ORDER BY difficulty_level;
|
|
SELECT * FROM problem_detail_view WHERE problem_type = '例题';
|
|
|
|
-- 统计分析示例
|
|
SELECT * FROM chapter_knowledge_density ORDER BY knowledge_density DESC;
|
|
SELECT * FROM knowledge_examination_frequency WHERE total_references > 5;
|
|
|
|
-- 关系网络查询
|
|
SELECT * FROM knowledge_relation_network WHERE relation_type = '前置知识';
|
|
|
|
-- 学习路径查询
|
|
SELECT * FROM core_learning_path WHERE sequence_level <= 3;
|
|
|
|
-- 函数调用示例
|
|
SELECT * FROM get_knowledge_prerequisite_chain('K1-1-3-01');
|
|
SELECT * FROM get_problem_recommendations('K1-1-1-01', 3);
|
|
SELECT * FROM search_knowledge_content('函数定义', 'knowledge');
|
|
SELECT * FROM evaluate_knowledge_mastery(1, 'K1-1-1-01');
|
|
|
|
-- 数据质量检查
|
|
SELECT * FROM orphaned_knowledge_points;
|
|
SELECT * FROM missing_tags_check;
|
|
SELECT * FROM code_format_consistency;
|
|
*/ |