2010-10-14 27 views
14

Ho un tavolo normalizzato con una colonna che contiene un elenco separato da virgole che è una chiave esterna a un'altra tabella:MySQL: Split elenco separato da virgole in più righe

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

voglio leggere questi dati in una ricerca motore che non offre alcun linguaggio procedurale.

Quindi non v'è un modo per sia fare un join su questa colonna o esegue una query su questi dati che inserisce voci appropriate in una nuova tabella? I dati risultanti dovrebbe assomigliare a questa:

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

riuscivo a pensare a una soluzione, se il DBMS funzioni che restituiscono un tavolo supportati ma MySQL a quanto pare non è così.

risposta

9

In MySQL ciò può essere ottenuto come sotto

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 | 
+---------------------+ 

Ora per ottenere la lunghezza separati da virgola vehicle_ids utilizzare al di sotto di query

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

Così utile, ho a che fare con un DB con dati CSV anche in alcune colonne – lintuxvi

5

Ho risposto a due domande simili in tanti giorni ma non ho ricevuto alcuna risposta, quindi suppongo che le persone siano scoraggiate dall'uso del cursore, ma come dovrebbe essere un processo a sé stante personalmente non penso che importi.

Come hai affermato, MySQL non supporta i tipi di restituzione delle tabelle, quindi non hai altra scelta se non eseguire il ciclo della tabella e analizzare la stringa csv del materiale e generare le righe appropriate per la parte e il materiale.

I seguenti messaggi possono rivelarsi di interesse:

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

Non è sicuro se è possibile farlo senza un ciclo, a meno che non ci sia un numero massimo di valori preimpostato che possono essere nei valori delimitati da virgole ... sei un po 'forzato ad un ciclo – Twelfth

+0

Sì, dovrai loop - come affermato. –

+0

Non è la soluzione migliore perché prende il problema dall'insieme del livello teorico al livello procedurale e quindi può essere usato solo come preparazione, non in tempo reale (risponde alla mia domanda "o", non alla mia "o") ma almeno funziona . Grazie. :) – AndreKR

0

È inoltre possibile utilizzare REGEXP

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

Questo vi aiuterà se si desidera prendi solo una pa rt. Non l'intera tabella naturalmente

+6

Grazie per la tua risposta, ma penso che il tuo SQL non abbia alcun senso. :) – AndreKR

1

MySQL non ha il riutilizzo della tabella temporanea e le funzioni non restituiscono righe.

Non riesco a trovare nulla in Stack Overflow per convertire la stringa di interi csv in righe, quindi ho scritto il mio in 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',',') 

Avrete anche bisogno di trasmettere a tipi diversi se non state usando ints.

Problemi correlati