現狀:`name` 欄位存 `aaa,bbb,ccc`,想查「包含多個值」的行。直接 SQL 判斷極其低效且違反關係型資料庫第一範式 (1NF)。
-- 原表
CREATE TABLE entity (id INT, name VARCHAR(200)); -- name 存 "aaa,bbb,ccc"
-- 重構為兩張表
CREATE TABLE entity (id INT, ...);
CREATE TABLE entity_name (entity_id INT, name VARCHAR(50), PRIMARY KEY (entity_id, name));
-- 查詢「有多個 name」變得極簡單且走索引
SELECT entity_id, COUNT(*) AS cnt FROM entity_name GROUP BY entity_id HAVING cnt > 1;
ALTER TABLE entity MODIFY name JSON; -- 存 ["aaa","bbb","ccc"]
-- 查詢包含多個元素
SELECT * FROM entity WHERE JSON_LENGTH(name) > 1;
-- 查詢包含特定值
SELECT * FROM entity WHERE JSON_CONTAINS(name, '"bbb"');
MySQL 無內建 `SPLIT_STRING`,需自建函數:
CREATE FUNCTION SPLIT_STR(str VARCHAR(255), delim VARCHAR(12), pos INT)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, pos),
LENGTH(SUBSTRING_INDEX(str, delim, pos - 1)) + 1), delim, '');
查詢邏輯:
SELECT * FROM entity
WHERE SPLIT_STR(name, ',', 2) != ''; -- 至少有兩段
結論:**違反 1NF 的設計,查詢永遠沒有好效能。** 能改結構就改,不能改上 JSON,實在不行寫函數並接受慢查詢風險。