2 votes

DB2 - Comment obtenir plusieurs positions pour un caractère dans une chaîne de caractères ?

J'ai donc le plaisir de travailler avec une très vieille base de données qui a apparemment été créée avant l'invention de la normalisation. On m'a demandé de trouver un moyen de la faire fonctionner correctement.

La première table dispose en fait d'une véritable clé primaire. exemple :

ID, Reason
--- ----------
 1, Write off
 2, Overage
 3, OLH

Le problème, c'est que l'autre table...

CustomerNum, JobNum, Reasons
------------ ------- ---------------------
      42351,     46, X
      32313,    456,    X
      85472,     13,   X    X

Comment ces tables sont-elles reliées dans leur système ? Oui, la position des X dans la ligne. Ainsi, si le X est en première position, il s'agit de la raison 1, en deuxième position, de la raison 2, et ainsi de suite. Il s'agit essentiellement d'un tableau plat. Et ce ne serait pas si mal en fait, s'ils se limitaient à 1 X par ligne... ( LOCATE('X', REASONS) as XINDEX ), mais ce n'est pas le cas. En théorie, il y a 21 X possibles qui peuvent être vérifiés sur chaque ligne.

Je dois donc leur donner une recommandation sur la manière d'y parvenir.
L'une de mes premières recommandations sera de créer un tableau séparé et de normaliser les tableaux, mais je ne sais pas si cela sera bien perçu ou s'ils seront prêts à modifier leur système.
J'aimerais donc suggérer quelque chose comme une procédure stockée qui serait capable de parcourir chaque ligne et de renvoyer les index comme s'ils se trouvaient dans une table séparée.

Je ne sais pas si c'est possible, mais j'ai bon espoir.

EDIT

Alors oui, je suis vraiment va pousser la table de liaison.
Voici l'alternative que j'ai trouvée en m'inspirant des suggestions :

Select tblCustomers.*, 
CASE WHEN SUBSTRING(Reasons,1,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 1)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,2,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 2)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,3,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 3)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,4,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 4)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,5,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 5)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,6,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 6)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,7,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 7)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,8,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 8)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,9,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 9)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,10,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 10)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,11,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 11)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,12,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 12)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,13,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 13)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,14,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 14)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,15,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 15)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,16,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 16)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,17,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 17)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,18,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 18)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,19,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 19)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,20,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 20)) || ', ' ELSE '' END 
|| CASE WHEN SUBSTRING(Reasons,21,1) = 'X' THEN RTRIM((SELECT Reason FROM tblReasons WHERE ID = 21)) || ', ' ELSE '' END AS XPOS 
From tblCustomers

Je vais devoir jouer un peu avec la suggestion de Marlin pour voir dans quelle mesure elle la rationalise, mais une chose que j'aime bien dans cette requête, c'est qu'elle montre à quel point leur présentation actuelle est ridicule, et pourquoi ils devraient la changer.

1voto

Zdravko Danev Points 6156

La première chose à faire est de créer une nouvelle colonne pour chaque position possible du X (donc s'il y a 10 positions -> 10 nouvelles colonnes) et de donner à ces colonnes des noms significatifs. ensuite, vous pouvez écrire des requêtes plus facilement...

1voto

Marlin Pierce Points 5558

J'aimerais vraiment présenter la nouvelle table de liaison, mais voici soit le contenu de la procédure stockée, soit la façon de remplir la table de liaison :

SELECT Customers.CustomerNum, Reasons.ID
FROM Customers, Reasons
WHERE SUBSTR(Customers.Reasons, Reasons.ID, 1) = 'X'

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X