2010-10-14 50 views
14

Tôi có một bảng unnormalized với một cột chứa một danh sách tách dấu phẩy đó là một khóa ngoại đến bảng khác:MySQL: Tách dấu phẩy tách ra danh sách thành nhiều hàng

+----------+-------------+ +--------------+-------+ 
| part_id | material | | material_id | name | 
+----------+-------------+ +--------------+-------+ 
|  339 | 1.2mm;1.6mm | |   1 | 1.2mm | 
|  970 | 1.6mm  | |   2 | 1.6mm | 
+----------+-------------+ +--------------+-------+ 

Tôi muốn đọc dữ liệu này vào một tìm kiếm động cơ không cung cấp ngôn ngữ thủ tục.

Vậy là có một cách để hai làm một tham gia vào cột này hay chạy một truy vấn trên dữ liệu này mà chèn mục thích hợp vào một bảng mới? Các dữ liệu kết quả sẽ giống như thế này:

+---------+-------------+ 
| part_id | material_id | 
+---------+-------------+ 
|  339 |   1 | 
|  339 |   2 | 
|  970 |   2 | 
+---------+-------------+ 

tôi có thể nghĩ ra một giải pháp nếu DBMS chức năng trả về một bảng hỗ trợ nhưng MySQL rõ ràng thì không.

Trả lời

9

Trong MySQL này có thể đạt được như sau

SELECT id, length FROM vehicles WHERE id IN (117, 148, 126) 

+---------------+ 
| id | length | 
+---------------+ 
| 117 | 25  | 
| 126 | 8  | 
| 148 | 10  | 
+---------------+ 

SELECT id,vehicle_ids FROM load_plan_configs WHERE load_plan_configs.id =42 

+---------------------+ 
| id | vehicle_ids | 
+---------------------+ 
| 42 | 117, 148, 126 | 
+---------------------+ 

Bây giờ để có được chiều dài của dấu phẩy tách vehicle_ids sử dụng dưới đây truy vấn

Output 

SELECT length 
FROM vehicles, load_plan_configs 
WHERE load_plan_configs.id = 42 AND FIND_IN_SET(
     vehicles.id, load_plan_configs.vehicle_ids 
) 

+---------+ 
| length | 
+---------+ 
| 25  | 
| 8  | 
| 10  | 
+---------+ 

For more info visit http://amitbrothers.blogspot.in/2014/03/mysql-split-comma-separated-list-into.html

+0

Rất hữu ích, tôi đang xử lý DB với dữ liệu CSV trong một số cột nhất định – lintuxvi

5

Tôi đã trả lời hai câu hỏi tương tự trong nhiều ngày nhưng không có bất kỳ câu trả lời nào vì vậy tôi đoán mọi người bị tắt bằng cách sử dụng con trỏ nhưng vì nó nên là một quá trình tắt cá nhân tôi không nghĩ rằng vấn đề.

Như bạn đã nói, MySQL không hỗ trợ các loại bảng trả về, vì vậy bạn có ít tùy chọn hơn là lặp bảng và phân tích cú pháp chuỗi csv và tạo các hàng thích hợp cho phần và tài liệu.

Các bài viết sau đây có thể chứng minh quan tâm:

split keywords for post php mysql

MySQL procedure to load data from staging table to other tables. Need to split up multivalue field in the process

Rgds

+0

Không chắc chắn nếu bạn có thể làm điều đó mà không có vòng lặp, trừ khi có một số giá trị đặt trước tối đa có thể nằm trong giá trị được phân cách bằng dấu phẩy ... bạn sắp bị buộc phải lặp lại – Twelfth

+0

Có bạn sẽ phải vòng lặp - như đã nêu. –

+0

Không phải là giải pháp tốt nhất vì nó có vấn đề từ cấp độ thiết lập đến cấp độ thủ tục và do đó chỉ có thể được sử dụng để chuẩn bị, chứ không phải trong thời gian thực (câu trả lời của tôi "hoặc", không phải của tôi "hoặc" câu hỏi), nhưng ít nhất nó hoạt động . Cảm ơn. :) – AndreKR

0

Bạn cũng có thể sử dụng REGEXP

SET @materialids=SELECT material FROM parttable where part_id=1; 
SELECT * FROM material_id WHERE REGEXP CONCAT('^',@materialids,'$'); 

này sẽ giúp đỡ nếu bạn muốn nhận được chỉ một pa rt. Không phải toàn bộ bảng dĩ nhiên

+6

Cảm ơn câu trả lời của bạn, nhưng tôi nghĩ rằng SQL của bạn không có ý nghĩa gì cả. :) – AndreKR

1

MySQL không có bảng tạm thời sử dụng lại và chức năng không trả lại hàng.

Tôi không thể tìm thấy bất kỳ thứ gì trong Stack Overflow để chuyển đổi chuỗi số nguyên csv thành hàng nên tôi đã tự viết bằng MySQL.

DELIMITER $$ 

DROP PROCEDURE IF EXISTS str_split $$ 
CREATE PROCEDURE str_split(IN str VARCHAR(4000),IN delim varchar(1)) 
begin 
DECLARE delimIdx int default 0; 
DECLARE charIdx int default 1; 
DECLARE rest_str varchar(4000) default ''; 
DECLARE store_str varchar(4000) default ''; 

create TEMPORARY table IF NOT EXISTS ids as (select parent_item_id from list_field where 1=0); 
truncate table ids; 
set @rest_str = str; 
set @delimIdx = LOCATE(delim,@rest_str); 
set @charIdx = 1; 
set @store_str = SUBSTRING(@rest_str,@charIdx,@delimIdx-1); 
set @rest_str = SUBSTRING(@rest_str from @delimIdx+1); 

if length(trim(@store_str)) = 0 then 
    set @store_str = @rest_str; 
end if;  


INSERT INTO ids 
SELECT (@store_str + 0); 

WHILE @delimIdx <> 0 DO 
    set @delimIdx = LOCATE(delim,@rest_str); 
    set @charIdx = 1; 
    set @store_str = SUBSTRING(@rest_str,@charIdx,@delimIdx-1); 
    set @rest_str = SUBSTRING(@rest_str from @delimIdx+1); 

select @store_str; 
    if length(trim(@store_str)) = 0 then 
     set @store_str = @rest_str; 
    end if;  
    INSERT INTO ids(parent_item_id) 
    SELECT (@store_str + 0);`enter code here` 
END WHILE; 

select parent_item_id from ids; 
end$$ 
DELIMITER ; 

call str_split('1,2,10,13,14',',') 

Bạn cũng sẽ cần phải truyền sang các loại khác nhau nếu bạn không sử dụng int.

Các vấn đề liên quan