Nó không phải là công việc cho DB
nhưng có thể:
CREATE TABLE tab(id INT, col VARCHAR(100));
INSERT INTO tab(id, col)
VALUES (1, 'option[A]sum[A]g3et[B]'), (2, '[Cosi]sum[A]g3et[ZZZZ]');
SELECT DISTINCT *
FROM (
SELECT id, RIGHT(val, LENGTH(val) - LOCATE('[', val)) AS val
FROM
(
SELECT id, SUBSTRING_INDEX(SUBSTRING_INDEX(t.col, ']', n.n), ']', -1) AS val
FROM tab t
CROSS JOIN
(
SELECT a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
) n
WHERE n.n <= 1 + (LENGTH(t.col) - LENGTH(REPLACE(t.col, ']', '')))
) sub
) s
WHERE val <> ''
ORDER BY ID;
Lưu ý:
Tùy thuộc vào col
độ dài tối đa mà bạn có thể cần để tạo nhiều số hơn trong CROSS JOIN
tiết diện. Hiện tại, nó đã lên đến 100.
Đầu ra:
Cách hoạt động:
- Tạo bảng số với
CROSS JOIN
- Tách chuỗi dựa trên
]
như kẻ mê sảng -
RIGHT(val, LENGTH(val) - LOCATE('[', val))
xóa phần lên đến[
- lọc ra các bản ghi trống
- Chỉ nhận
DISTINCT
giá trị
Truy vấn bên trong nhất:
╔════╦══════════╗
║ id ║ val ║
╠════╬══════════╣
║ 1 ║ option[A ║
║ 1 ║ sum[A ║
║ 1 ║ g3et[B ║
║ 1 ║ ║
╚════╩══════════╝
Truy vấn con thứ hai:
╔════╦═════╗
║ id ║ val ║
╠════╬═════╣
║ 1 ║ A ║
║ 1 ║ A ║
║ 1 ║ B ║
║ 1 ║ ║
╚════╩═════╝
Và truy vấn ngoài cùng:
╔════╦═════╗
║ id ║ val ║
╠════╬═════╣
║ 1 ║ A ║
║ 1 ║ B ║
╚════╩═════╝
Vì vậy, hãy thêm đơn giản:
WHERE n.n <= 1 + (LENGTH(t.col) - LENGTH(REPLACE(t.col, ']', '')))
AND t.id = ?
CHỈNH SỬA 2:
Bạn muốn phân tích cú pháp JSON trong MySQL. Như tôi đã nói trước khi phân tích cú pháp và nhận giá trị trong lớp ứng dụng. Câu trả lời này chỉ dành cho mục đích demo / đồ chơi và sẽ có hiệu suất rất thấp.
Nếu bạn vẫn nhấn mạnh vào giải pháp SQL:
SELECT id, val,s.n
FROM (
SELECT id, RIGHT(val, LENGTH(val) - LOCATE('[', val)) AS val,n
FROM
(
SELECT id, SUBSTRING_INDEX(SUBSTRING_INDEX(t.col, ']', n.n), ']', -1) AS val, n.n
FROM (SELECT id, REPLACE(col, '[]','') as col FROM tab) t
CROSS JOIN
(
SELECT e.N * 10000 + d.N * 1000 + c.N * 100 + a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) c
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) d
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) e
) n
WHERE n.n <= 1 + (LENGTH(t.col) - LENGTH(REPLACE(t.col, ']', '')))
) sub
) s
WHERE val <> ''
GROUP BY id, val
HAVING n <> MAX(n)
ORDER BY id,n;
Đầu ra:
╔═════╦═════════════╦════╗
║ id ║ val ║ n ║
╠═════╬═════════════╬════╣
║ 1 ║ CE31285LV4 ║ 1 ║
║ 1 ║ D32E ║ 3 ║
║ 1 ║ GTX750 ║ 5 ║
║ 1 ║ M256S ║ 7 ║
║ 1 ║ H2X1T ║ 9 ║
║ 1 ║ FMLANE4U4 ║ 11 ║
╚═════╩═════════════╩════╝
CHỈNH SỬA 3:
CROSS JOIN
và toàn bộ truy vấn con chỉ là bảng kiểm đếm. Đó là tất cả. Nếu MySQL
có chức năng tạo chuỗi số (như generate_series
hoặc bảng số được mô phỏng trước thì không cần CROSS JOIN
.
Bảng số là cần thiết cho SUBSTRING_INDEX
: