2009-11-04 8 views
1

Il suffit de demander, Existe-t-il une fonction disponible dans mysql pour diviser les éléments d'une seule ligne en plusieurs colonnes? J'ai une ligne de table avec les champs, user_id, user_name, user_location.Comment diviser une seule ligne en plusieurs colonnes dans mysql

Dans ce un utilisateur peut ajouter plusieurs emplacements. J'implose les emplacements et les stocke dans une table comme une rangée utilisant php. Lorsque je montre les enregistrements d'utilisateur dans une vue de grille, je rencontre un problème de pagination car je montre les enregistrements en séparant les emplacements_utilisateur. J'ai donc besoin de diviser les user_locations (une seule ligne en plusieurs colonnes).

Existe-t-il une fonction disponible dans mysql pour diviser et compter les enregistrements par caractère (%).

Par exemple, le USER_LOCATION ayant US%UK%JAPAN%CANADA

Comment puis-je partager ce record en 4 colonnes. Je dois également vérifier les valeurs de comptage (4). Merci d'avance.

Répondre

2

d'abord normaliser la chaîne, la suppression des emplacements vides et faire en sorte il y a un% à la fin:

select replace(concat(user_location,'%'),'%%','%') as str 
from YourTable where user_id = 1 

Ensuite, nous pouvons compter le nombre d'entrées avec un tour. Remplacez '%' par '%' et comptez le nombre d'espaces ajoutés à la chaîne. Par exemple:

select length(replace(str, '%', '% ')) - length(str) 
    as LocationCount  
from (
    select replace(concat(user_location,'%'),'%%','%') as str 
    from YourTable where user_id = 1 
) normalized 

En utilisant SUBSTRING_INDEX, nous pouvons ajouter des colonnes pour un certain nombre d'emplacements:

select length(replace(str, '%', '% ')) - length(str) 
    as LocationCount  
, substring_index(substring_index(str,'%',1),'%',-1) as Loc1 
, substring_index(substring_index(str,'%',2),'%',-1) as Loc2 
, substring_index(substring_index(str,'%',3),'%',-1) as Loc3 
from (
    select replace(concat(user_location,'%'),'%%','%') as str 
    from YourTable where user_id = 1 
) normalized 

Pour votre exemple US%UK%JAPAN%CANADA, cette impression:

LocationCount Loc1 Loc2 Loc3 
4    US  UK  JAPAN 

Donc, vous voyez qu'il peut être fait, mais l'analyse des chaînes n'est pas l'une des forces de SQL.

+0

Merci pour votre requête. mais le nombre Numberoflocations retournant seulement 1 lorsque les emplacements sont plus d'un dans le tableau – Paulraj

+0

Droit, je pense que je vois ce que vous voulez dire maintenant. Je vais éditer la réponse. – Andomar

0

Vous devriez le faire dans votre application client, pas dans la base de données. Lorsque vous effectuez une requête SQL, vous devez spécifier de manière statique les colonnes que vous voulez obtenir, c'est-à-dire indiquer au DB les colonnes que vous voulez dans votre resultset AVANT de l'exécuter. Par exemple, si vous avez un datetime stocké, vous pouvez faire quelque chose comme select month(birthday), select year(birthday) from ..., dans ce cas, nous divisons la colonne anniversaire en 2 autres colonnes, mais il est spécifié dans la requête quelles colonnes nous aurons.

Dans votre cas, vous devez obtenir exactement cette chaîne US%UK%JAPAN%CANADA de la base de données, puis vous diviser plus tard dans votre logiciel, à savoir

/* get data from database */ 
/* ... */ 
$user_location = ... /* extract the field from the resultset */ 
$user_locations = explode("%", $user_location); 
0

Ceci est une mauvaise conception, si vous pouvez le modifier, stocker les données dans 2 tables:

table users: id, name, surname ... 

table users_location: user_id (fk), location 

users_location aurait une clé étrangère aux utilisateurs répercutant champ user_id

2

La « bonne chose » serait diviser les emplacements à une autre table et établir une relation plusieurs-à-plusieurs entre eux.Ensuite, assurez-vous de l'intégrité référentielle à l'aide de clés étrangères (et du moteur InnoDB) ou de déclencheurs.

1

cela devrait le faire

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `CSV2LST`$$ 

CREATE DEFINER=`root`@`%` PROCEDURE `CSV2LST`(IN csv_ TEXT) 
BEGIN 

SET @s=CONCAT('select \"',REPLACE(csv_,',','\" union select \"'),'\";'); 
PREPARE stmt FROM @s; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 
END$$ 

DELIMITER ; 
Questions connexes