优化版三国主题MySQL建表与查询练习(细节增强)

文章目录

  • 优化版三国主题MySQL建表与查询练习(细节增强)
    • 题目一:三国人物信息表(全面优化)
      • 建表语句(增强约束与注释)
      • 插入数据(含完整信息)
      • 查询练习(增强实用性)
    • 题目二:三国战役表(增强关系设计)
      • 建表语句(完整关系模型)
      • 插入数据(完整战役信息)
      • 查询练习(多表关联)
    • 综合实战演练
      • 1. 人物能力值分析
      • 2. 战役地图查询
      • 3. 胜负因素分析
    • 设计亮点总结

优化版三国主题MySQL建表与查询练习(细节增强)

题目一:三国人物信息表(全面优化)

建表语句(增强约束与注释)

-- 创建势力表(预定义势力)
CREATE TABLE kingdoms (
    kingdom_id TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(10) NOT NULL UNIQUE
) COMMENT '三国势力表';

-- 插入基本势力
INSERT INTO kingdoms (name) VALUES ('魏'), ('蜀'), ('吴'), ('其他');

-- 创建人物主表
CREATE TABLE heroes (
    id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
    name VARCHAR(20) NOT NULL COMMENT '人物姓名',
    kingdom_id TINYINT UNSIGNED NOT NULL COMMENT '所属势力ID',
    role ENUM('君主', '武将', '谋士', '文官') NOT NULL COMMENT '角色类型',
    strength TINYINT UNSIGNED DEFAULT 0 COMMENT '武力值(0-100)',
    intelligence TINYINT UNSIGNED DEFAULT 0 COMMENT '智力值(0-100)',
    birth_year SMALLINT COMMENT '出生年份',
    death_year SMALLINT COMMENT '死亡年份',
    gender ENUM('男', '女') NOT NULL DEFAULT '男' COMMENT '性别',
    CONSTRAINT chk_stats CHECK (strength BETWEEN 0 AND 100 AND intelligence BETWEEN 0 AND 100),
    CONSTRAINT fk_kingdom FOREIGN KEY (kingdom_id) REFERENCES kingdoms(kingdom_id)
) ENGINE=InnoDB COMMENT '三国人物信息表';

-- 创建索引(优化查询性能)
CREATE INDEX idx_heroes_role ON heroes(role);
CREATE INDEX idx_heroes_name ON heroes(name);

插入数据(含完整信息)

-- 插入势力数据(已在建表时完成)

-- 插入人物数据
INSERT INTO heroes (name, kingdom_id, role, strength, intelligence, birth_year, death_year, gender) VALUES
('刘备', (SELECT kingdom_id FROM kingdoms WHERE name='蜀'), '君主', 75, 85, 161, 223, '男'),
('关羽', (SELECT kingdom_id FROM kingdoms WHERE name='蜀'), '武将', 95, 75, 160, 220, '男'),
('张飞', (SELECT kingdom_id FROM kingdoms WHERE name='蜀'), '武将', 92, 60, 168, 221, '男'),
('诸葛亮', (SELECT kingdom_id FROM kingdoms WHERE name='蜀'), '谋士', 65, 99, 181, 234, '男'),
('曹操', (SELECT kingdom_id FROM kingdoms WHERE name='魏'), '君主', 80, 90, 155, 220, '男'),
('司马懿', (SELECT kingdom_id FROM kingdoms WHERE name='魏'), '谋士', 70, 95, 179, 251, '男'),
('孙权', (SELECT kingdom_id FROM kingdoms WHERE name='吴'), '君主', 70, 85, 182, 252, '男'),
('周瑜', (SELECT kingdom_id FROM kingdoms WHERE name='吴'), '谋士', 75, 95, 175, 210, '男'),
('吕布', (SELECT kingdom_id FROM kingdoms WHERE name='其他'), '武将', 99, 40, 161, 199, '男'),
('貂蝉', (SELECT kingdom_id FROM kingdoms WHERE name='其他'), '谋士', 30, 85, NULL, NULL, '女'),
('孙尚香', (SELECT kingdom_id FROM kingdoms WHERE name='吴'), '武将', 82, 75, 184, NULL, '女'),
('黄月英', (SELECT kingdom_id FROM kingdoms WHERE name='蜀'), '谋士', 40, 92, 185, 219, '女');

查询练习(增强实用性)

  1. 基础联合查询

    -- 查询所有人物及其所属势力
    SELECT h.name, k.name AS kingdom, h.role, h.strength, h.intelligence
    FROM heroes h
    JOIN kingdoms k ON h.kingdom_id = k.kingdom_id;
    
  2. 高级统计查询

    -- 各势力文官平均智力值排行
    SELECT 
        k.name AS 势力,
        COUNT(*) AS 文官人数,
        AVG(h.intelligence) AS 平均智力值
    FROM heroes h
    JOIN kingdoms k ON h.kingdom_id = k.kingdom_id
    WHERE h.role IN ('谋士', '文官')
    GROUP BY k.name
    ORDER BY 平均智力值 DESC;
    
  3. 条件计算查询

    -- 查询健在人物的年龄(假设当前是公元230年)
    SELECT 
        name,
        birth_year,
        230 - birth_year AS 年龄,
        CASE 
            WHEN gender = '女' THEN CONCAT('女士')
            ELSE CONCAT('先生')
        END AS 称谓
    FROM heroes
    WHERE death_year IS NULL
    ORDER BY 年龄 DESC;
    

题目二:三国战役表(增强关系设计)

建表语句(完整关系模型)

-- 创建战役类型表
CREATE TABLE battle_types (
    type_id TINYINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(20) NOT NULL COMMENT '战役类型',
    description VARCHAR(100) COMMENT '类型说明'
);

-- 插入战役类型
INSERT INTO battle_types (name, description) VALUES
('水战', '水上作战'),
('陆战', '陆地作战'),
('攻城战', '城市攻防战'),
('伏击战', '埋伏奇袭作战'),
('遭遇战', '意外遭遇作战');

-- 创建战役主表
CREATE TABLE battles (
    battle_id INT AUTO_INCREMENT PRIMARY KEY COMMENT '战役ID',
    name VARCHAR(30) NOT NULL UNIQUE COMMENT '战役名称',
    year SMALLINT NOT NULL COMMENT '发生年份',
    location VARCHAR(50) NOT NULL COMMENT '发生地点(古地名)',
    location_now VARCHAR(50) COMMENT '现代地名',
    attacker_kingdom_id TINYINT UNSIGNED NOT NULL COMMENT '进攻方势力ID',
    defender_kingdom_id TINYINT UNSIGNED NOT NULL COMMENT '防守方势力ID',
    type_id TINYINT UNSIGNED NOT NULL COMMENT '战役类型ID',
    result ENUM('进攻方胜', '防守方胜', '平局', '无结果') NOT NULL COMMENT '战役结果',
    duration_days SMALLINT UNSIGNED COMMENT '持续天数',
    CONSTRAINT fk_attacker FOREIGN KEY (attacker_kingdom_id) REFERENCES kingdoms(kingdom_id),
    CONSTRAINT fk_defender FOREIGN KEY (defender_kingdom_id) REFERENCES kingdoms(kingdom_id),
    CONSTRAINT fk_battle_type FOREIGN KEY (type_id) REFERENCES battle_types(type_id)
) COMMENT '三国战役记录表';

-- 创建战役人物关联表
CREATE TABLE battle_commanders (
    battle_id INT NOT NULL COMMENT '战役ID',
    commander_id INT NOT NULL COMMENT '主将ID',
    role ENUM('主将', '副将', '军师') NOT NULL COMMENT '角色',
    is_attacker BOOLEAN NOT NULL COMMENT '是否进攻方',
    PRIMARY KEY (battle_id, commander_id),
    FOREIGN KEY (battle_id) REFERENCES battles(battle_id),
    FOREIGN KEY (commander_id) REFERENCES heroes(id)
) COMMENT '战役指挥官表';

插入数据(完整战役信息)

-- 插入战役数据
INSERT INTO battles (name, year, location, location_now, attacker_kingdom_id, defender_kingdom_id, type_id, result, duration_days) VALUES
('赤壁之战', 208, '赤壁', '湖北赤壁市', 
    (SELECT kingdom_id FROM kingdoms WHERE name='魏'),
    (SELECT kingdom_id FROM kingdoms WHERE name='吴'),
    (SELECT type_id FROM battle_types WHERE name='水战'),
    '防守方胜', 60),
('官渡之战', 200, '官渡', '河南中牟县', 
    (SELECT kingdom_id FROM kingdoms WHERE name='魏'),
    (SELECT kingdom_id FROM kingdoms WHERE name='其他'), -- 袁绍势力
    (SELECT type_id FROM battle_types WHERE name='陆战'),
    '进攻方胜', 120),
('夷陵之战', 222, '夷陵', '湖北宜昌市', 
    (SELECT kingdom_id FROM kingdoms WHERE name='蜀'),
    (SELECT kingdom_id FROM kingdoms WHERE name='吴'),
    (SELECT type_id FROM battle_types WHERE name='遭遇战'),
    '防守方胜', 90),
('合肥之战', 215, '合肥', '安徽合肥市', 
    (SELECT kingdom_id FROM kingdoms WHERE name='吴'),
    (SELECT kingdom_id FROM kingdoms WHERE name='魏'),
    (SELECT type_id FROM battle_types WHERE name='攻城战'),
    '防守方胜', 45),
('汉中之战', 219, '汉中', '陕西汉中市', 
    (SELECT kingdom_id FROM kingdoms WHERE name='蜀'),
    (SELECT kingdom_id FROM kingdoms WHERE name='魏'),
    (SELECT type_id FROM battle_types WHERE name='攻城战'),
    '进攻方胜', 180);

-- 插入战役主将数据
INSERT INTO battle_commanders (battle_id, commander_id, role, is_attacker) VALUES
-- 赤壁之战
((SELECT battle_id FROM battles WHERE name='赤壁之战'),
    (SELECT id FROM heroes WHERE name='曹操'), '主将', 1),
((SELECT battle_id FROM battles WHERE name='赤壁之战'),
    (SELECT id FROM heroes WHERE name='周瑜'), '主将', 0),
    
-- 官渡之战
((SELECT battle_id FROM battles WHERE name='官渡之战'),
    (SELECT id FROM heroes WHERE name='曹操'), '主将', 1),

-- 夷陵之战
((SELECT battle_id FROM battles WHERE name='夷陵之战'),
    (SELECT id FROM heroes WHERE name='刘备'), '主将', 1),
((SELECT battle_id FROM battles WHERE name='夷陵之战'),
    (SELECT id FROM heroes WHERE name='陆逊'), '主将', 0),
    
-- 合肥之战
((SELECT battle_id FROM battles WHERE name='合肥之战'),
    (SELECT id FROM heroes WHERE name='张辽'), '主将', 0),
    
-- 汉中之战
((SELECT battle_id FROM battles WHERE name='汉中之战'),
    (SELECT id FROM heroes WHERE name='刘备'), '主将', 1),
((SELECT battle_id FROM battles WHERE name='汉中之战'),
    (SELECT id FROM heroes WHERE name='曹操'), '主将', 0);

查询练习(多表关联)

  1. 基础战役查询

    -- 查询赤壁之战详细信息
    SELECT 
        b.name AS 战役名称,
        b.year AS 年份,
        b.location_now AS 现代位置,
        attack.name AS 进攻方,
        defend.name AS 防守方,
        bt.name AS 战役类型,
        b.result AS 结果
    FROM battles b
    JOIN kingdoms attack ON b.attacker_kingdom_id = attack.kingdom_id
    JOIN kingdoms defend ON b.defender_kingdom_id = defend.kingdom_id
    JOIN battle_types bt ON b.type_id = bt.type_id
    WHERE b.name = '赤壁之战';
    
  2. 高级人物关联查询

    -- 查询曹操参与的所有战役
    SELECT 
        b.name AS 战役,
        b.year AS 年份,
        CASE 
            WHEN bc.is_attacker = 1 THEN '进攻方'
            ELSE '防守方'
        END AS 参战方,
        b.result AS 结果
    FROM battle_commanders bc
    JOIN battles b ON bc.battle_id = b.battle_id
    JOIN heroes h ON bc.commander_id = h.id
    WHERE h.name = '曹操';
    
  3. 统计型查询

    -- 各类型战役胜负统计
    SELECT
        bt.name AS 战役类型,
        COUNT(*) AS 总场次,
        SUM(CASE WHEN b.result = '进攻方胜' THEN 1 ELSE 0 END) AS 进攻方胜,
        SUM(CASE WHEN b.result = '防守方胜' THEN 1 ELSE 0 END) AS 防守方胜,
        SUM(CASE WHEN b.result IN ('平局', '无结果') THEN 1 ELSE 0 END) AS 平局无结果,
        ROUND(AVG(b.duration_days), 1) AS 平均持续天数
    FROM battles b
    JOIN battle_types bt ON b.type_id = bt.type_id
    GROUP BY bt.name;
    

综合实战演练

1. 人物能力值分析

-- 创建武将能力视图
CREATE VIEW commander_abilities AS
SELECT 
    h.name AS 姓名,
    k.name AS 势力,
    h.strength AS 武力,
    h.intelligence AS 智力,
    ROUND((h.strength + h.intelligence) / 2, 1) AS 综合能力,
    DENSE_RANK() OVER (ORDER BY (h.strength + h.intelligence) DESC) AS 能力排名
FROM heroes h
JOIN kingdoms k ON h.kingdom_id = k.kingdom_id
WHERE h.role IN ('君主', '武将', '谋士');

-- 使用视图查询
SELECT * FROM commander_abilities ORDER BY 能力排名 LIMIT 10;

2. 战役地图查询

-- 各战役位置地理分布
SELECT 
    b.location_now AS 现代位置,
    COUNT(*) AS 战役次数,
    GROUP_CONCAT(b.name ORDER BY b.year SEPARATOR '、') AS 战役列表
FROM battles b
GROUP BY b.location_now
HAVING COUNT(*) >= 1
ORDER BY COUNT(*) DESC;

3. 胜负因素分析

-- 主将能力对胜负的影响
SELECT 
    b.name AS 战役,
    CASE 
        WHEN b.result = '进攻方胜' THEN ac.name
        WHEN b.result = '防守方胜' THEN dc.name
        ELSE '平局'
    END AS 胜方主将,
    bc_att.武力 AS 胜方武力,
    bc_att.智力 AS 胜方智力,
    b.result AS 结果
FROM battles b
JOIN (
    SELECT battle_id, commander_id 
    FROM battle_commanders 
    WHERE role = '主将' AND is_attacker = 1
) att ON b.battle_id = att.battle_id
JOIN (
    SELECT battle_id, commander_id 
    FROM battle_commanders 
    WHERE role = '主将' AND is_attacker = 0
) def ON b.battle_id = def.battle_id
JOIN commander_abilities ac ON att.commander_id = ac.姓名
JOIN commander_abilities dc ON def.commander_id = dc.姓名;

设计亮点总结

  1. 规范化设计

    • 使用关联表而非枚举,便于扩展
    • 外键约束保证数据完整性
    • 适当的索引提高查询效率
  2. 历史准确性

    • 包含古今地名对照
    • 明确战役角色区分
    • 支持多人指挥同一战役
  3. 实用功能

    • 视图简化复杂查询
    • 计算字段丰富分析维度
    • 窗口函数实现高级排名
  4. 教学价值

    • 覆盖单表/多表操作
    • 包含增删改查全操作
    • 展示实际数据分析方法

这个优化版本更适合初学者学习,通过三国主题的实际案例,帮助掌握数据库设计的核心概念和SQL查询的精髓。

你可能感兴趣的:(五,MySQL运维DBA,mysql,数据库)