Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Làm cách nào để thay thế mọi trường hợp khác của một ký tự cụ thể trong chuỗi MySQL?

Bạn nên cân nhắc để lưu trữ dữ liệu của mình trong một lược đồ chuẩn hóa. Trong trường hợp của bạn, bảng sẽ giống như sau:

| id | k |        v |
|----|---|----------|
|  1 | A |       10 |
|  1 | B |       20 |
|  1 | C |       30 |
|  2 | A | Positive |
|  2 | B | Negative |

Lược đồ này linh hoạt hơn và bạn sẽ hiểu tại sao.

Vậy làm thế nào để chuyển đổi dữ liệu đã cho thành lược đồ mới? Bạn sẽ cần một bảng trợ giúp chứa số thứ tự. Vì cột của bạn là varchar(255) bạn chỉ có thể lưu trữ 128 giá trị (+ 127 dấu phân cách) trong đó. Nhưng chúng ta hãy chỉ tạo ra 1000 số. Bạn có thể sử dụng bất kỳ bảng nào có đủ hàng. Nhưng vì bất kỳ máy chủ MySQL nào đều có information_schema.columns bảng, tôi sẽ sử dụng nó.

drop table if exists helper_sequence;
create table helper_sequence (i int auto_increment primary key)
    select null as i
    from information_schema.columns c1
    join information_schema.columns c2
    limit 1000;

Chúng tôi sẽ sử dụng các số này làm vị trí của các giá trị trong chuỗi của bạn bằng cách kết hợp hai bảng.

Để trích xuất một giá trị từ một chuỗi được phân tách, bạn có thể sử dụng substring_index() hàm số. Giá trị ở vị trí i sẽ là

substring_index(substring_index(t.options, '|', i  ), '|', -1)

Trong chuỗi của bạn, bạn có một chuỗi các khóa theo sau là các giá trị của nó. Vị trí của một phím là một số lẻ. Vì vậy, nếu vị trí của khóa là i , vị trí của giá trị tương ứng sẽ là i+1

Để có được số lượng dấu phân cách trong chuỗi và giới hạn phép nối của chúng ta, chúng ta có thể sử dụng

char_length(t.options) - char_length(replace(t.options, '|', ''))

Truy vấn để lưu trữ dữ liệu ở dạng chuẩn hóa sẽ là:

create table normalized_table
    select t.id
        , substring_index(substring_index(t.options, '|', i  ), '|', -1) as k
        , substring_index(substring_index(t.options, '|', i+1), '|', -1) as v
    from old_table t
    join helper_sequence s
      on s.i <= char_length(t.options) - char_length(replace(t.options, '|', ''))
    where s.i % 2 = 1

Bây giờ, hãy chạy select * from normalized_table và bạn sẽ nhận được điều này:

| id | k |        v |
|----|---|----------|
|  1 | A |       10 |
|  1 | B |       20 |
|  1 | C |       30 |
|  2 | A | Positive |
|  2 | B | Negative |

Vậy tại sao định dạng này lại là sự lựa chọn tốt hơn? Bên cạnh nhiều lý do khác, một là bạn có thể dễ dàng chuyển đổi nó sang lược đồ cũ của mình với

select id, group_concat(concat(k, '|', v) order by k separator '|') as options
from normalized_table
group by id;

| id |               options |
|----|-----------------------|
|  1 |        A|10|B|20|C|30 |
|  2 | A|Positive|B|Negative |

hoặc sang định dạng mong muốn của bạn

select id, group_concat(concat(k, '|', v) order by k separator ',') as options
from normalized_table
group by id;

| id |               options |
|----|-----------------------|
|  1 |        A|10,B|20,C|30 |
|  2 | A|Positive,B|Negative |

Nếu bạn không quan tâm đến việc chuẩn hóa và chỉ muốn tác vụ này được hoàn thành, bạn có thể cập nhật bảng của mình bằng

update old_table o
join (
    select id, group_concat(concat(k, '|', v) order by k separator ',') as options
    from normalized_table
    group by id
) n using (id)
set o.options = n.options;

Và thả normalized_table .

Nhưng sau đó bạn sẽ không thể sử dụng các truy vấn đơn giản như

select *
from normalized_table
where k = 'A'

Xem bản trình diễn tại rextester.com



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cài đặt MySQL trên Ubuntu mà không có lời nhắc mật khẩu

  2. Mysql:không thể nhận thấy sau khi đọc bảng const

  3. Xem tài trợ trong MySQL

  4. Truy vấn SQL bị mắc kẹt trong trạng thái thống kê

  5. Gửi email từ trình kích hoạt MySQL khi một bảng được cập nhật