-- 寶寶信息表 (已接種記錄)
CREATE TABLE baby_vaccine_record (
id INT PRIMARY KEY AUTO_INCREMENT,
baby_id INT NOT NULL,
vaccine_id INT NOT NULL,
is_vaccined TINYINT DEFAULT 1, -- 1=已接種
vaccined_date DATE,
INDEX idx_baby (baby_id)
);
-- 疫苗基礎信息表 (所有疫苗)
CREATE TABLE vaccine_info (
vaccine_id INT PRIMARY KEY,
vaccine_name VARCHAR(100),
vaccine_type VARCHAR(50),
recommended_age VARCHAR(50)
);
結果需包含:疫苗名稱、類型、推薦年齡、**是否已接種 (是/否)**、接種日期 (未接種為 NULL)。
SELECT
vi.vaccine_id,
vi.vaccine_name,
vi.vaccine_type,
vi.recommended_age,
CASE WHEN bvr.is_vaccined = 1 THEN '已接種' ELSE '未接種' END AS status,
bvr.vaccined_date
FROM vaccine_info vi
LEFT JOIN baby_vaccine_record bvr
ON vi.vaccine_id = bvr.vaccine_id
AND bvr.baby_id = 12345 -- 目標寶寶 ID
ORDER BY vi.recommended_age; -- 或按 vaccine_id 排序
| 技術點 | 說明 |
|---|---|
LEFT JOIN |
保留左表 (vaccine_info) 所有行,右表無匹配則列為 NULL → 實現「未接種也顯示」。 |
ON 條件含 baby_id |
將過濾條件放在 ON 而非 WHERE,否則會過濾掉未接種行 (因 bvr.baby_id 為 NULL)。 |
CASE WHEN |
將 0/1 轉為可讀狀態文本。 |
| 索引優化 | baby_vaccine_record(baby_id, vaccine_id) 聯合索引加速 JOIN。 |
SELECT
vi.*,
(SELECT '已接種' FROM baby_vaccine_record bvr
WHERE bvr.vaccine_id = vi.vaccine_id AND bvr.baby_id = 12345 AND bvr.is_vaccined = 1
LIMIT 1) AS status,
(SELECT vaccined_date FROM baby_vaccine_record bvr
WHERE bvr.vaccine_id = vi.vaccine_id AND bvr.baby_id = 12345
LIMIT 1) AS vaccined_date
FROM vaccine_info vi;
<select id="selectVaccineStatusByBabyId" resultType="VaccineStatusVO">
SELECT vi.vaccine_id, vi.vaccine_name, vi.vaccine_type, vi.recommended_age,
CASE WHEN bvr.is_vaccined = 1 THEN '已接種' ELSE '未接種' END AS status,
bvr.vaccined_date
FROM vaccine_info vi
LEFT JOIN baby_vaccine_record bvr
ON vi.vaccine_id = bvr.vaccine_id
AND bvr.baby_id = #{babyId}
ORDER BY vi.vaccine_id
</select>