-- 核心表
CREATE TABLE `ask` (
`id` INT PRIMARY KEY,
`city_id` INT,
`borough_id` INT,
`answer_num` INT DEFAULT 0
);
CREATE TABLE `answer` (
`id` INT PRIMARY KEY,
`father_id` INT, -- 關聯 ask.id
`content` TEXT
);
CREATE TABLE `city` (
`id` INT PRIMARY KEY,
`name` VARCHAR(50)
);
CREATE TABLE `borough` (
`id` INT PRIMARY KEY,
`city_id` INT,
`name` VARCHAR(50)
);
SELECT a.id, COUNT(ans.father_id) AS cnt, a.answer_num
FROM `ask` AS a
LEFT JOIN `answer` AS ans ON a.id = ans.father_id
GROUP BY a.id
ORDER BY a.id;
LEFT JOIN 保證無回覆的問題也顯示(cnt=0)。
UPDATE `ask` AS a
JOIN `borough` AS b ON a.borough_id = b.id
SET a.city_id = b.city_id;
UPDATE ... JOIN ... SET 語法,原子執行。
UPDATE `ask` AS a
SET a.answer_num = (
SELECT COUNT(*)
FROM `answer`
WHERE father_id = a.id
);
⚠️ 無 WHERE 條件會全表更新,大表極慢。建議加條件:
UPDATE `ask` AS a
SET a.answer_num = (
SELECT COUNT(*) FROM `answer` WHERE father_id = a.id
)
WHERE a.id IN (SELECT DISTINCT father_id FROM `answer`); -- 僅更新有回覆的
UPDATE `ask` AS a
JOIN (
SELECT father_id, COUNT(*) AS cnt
FROM `answer`
GROUP BY father_id
) AS ans ON a.id = ans.father_id
SET a.answer_num = ans.cnt;
-- 存儲過程:分批更新 answer_num
DELIMITER $$
CREATE PROCEDURE batch_update_answer_num()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE v_max_id INT;
DECLARE v_batch_size INT DEFAULT 1000;
SELECT MAX(id) INTO v_max_id FROM `ask`;
WHILE done = 0 DO
UPDATE `ask` AS a
JOIN (
SELECT father_id, COUNT(*) AS cnt
FROM `answer`
WHERE father_id > (SELECT COALESCE(MAX(id),0) - v_batch_size FROM `ask`) -- 簡化邏輯,實際用游標
GROUP BY father_id
) AS ans ON a.id = ans.father_id
SET a.answer_num = ans.cnt
WHERE a.id > (SELECT COALESCE(MAX(id),0) - v_batch_size FROM `ask`) -- 示意
LIMIT v_batch_size;
IF ROW_COUNT() = 0 THEN SET done = 1; END IF;
-- 實際生產用游標/臨時表分批更可控
END WHILE;
END$$
DELIMITER ;
Subquery returns more than 1 row → 聚合加 GROUP BY 或 LIMIT 1(但邏輯需正確)。UPDATE t SET ... WHERE id IN (SELECT ... FROM t) → 用 JOIN 或 临时表 繞過。ON UPDATE CASCADE、觸發器,評估影響範圍。LEFT JOIN + GROUP BY,被驅動表關聯列有索引。