Convertir des strings dans plusieurs formats en un seul format standard

Je mets à jour une table en utilisant une procédure stockée qui importe des informations de SSRS. J'ai un champ qui s'appelle la page. Le champ de page peut contenir l'un des trois formats suivants:

  1. Un champ purement numérique, par exemple 1,2 3 etc.
  2. Une combinaison de numbers et de lettres, par exemple 1D, 4C, 7Z etc.
  3. Un numéro, un tiret et deux numéros supplémentaires, par exemple 2-01, 3-04, 1-09, etc.

Je dois créer une équivalence de page pour chacun des formats à des fins de sorting ainsi que pour aider à définir une catégorie générale de numéros de pages. L'exemple 1 est une page de base, l'exemple 2 est une page d'art et l'exemple 3 est une page de text.

Pour l'équivalence, l'exemple 1 donnerait un format de 1,00. L'exemple 2 aboutirait à une équivalence de 1,01 à 1,26 basée sur l'équivalent numérique de la lettre. Finalement, l'exemple 3 donnerait 1,26 plus 0,01 * la valeur à la droite du tiret. La valeur minimale est 1,27.

Je l'ai fait dans Excel mais n'arrive pas à écrire la formule correctement dans SQL.

J'utilise SQL Server 2008 R2

Cela semble couvrir les cas que vous décrivez:

declare @t table (val varchar(10)) insert into @t select '1' union select '2' union select '1D' union select '4S' union select '2-01' union select '1-09' select val, case when val not like '%[^0-9]%' then val + '.00' when val like '[0-9][AZ]' then '1.' + right('0' + convert(varchar, ascii(right(val, 1))-64), 2) when val like '%-%' then convert(varchar, 1.26 + (0.01 * cast(subssortingng(val, charindex('-', val)+1, 2) as int))) else val end from @t 

TSQL n'est pas un bon langage pour la manipulation et l'parsing de strings, vous pouvez donc envisager d'utiliser une fonction CLR ou une procédure stockée pour cela. Et l'application de ces règles est un bon candidat pour les tests unitaires, car il est simple de définir et d'utiliser un set de test de valeurs d'input et de sortie pour vérifier votre code.

Voici une autre option.

Bien que cette réponse soit basée sur celle de Pondlife , elle renvoie decimal résultats decimal au lieu de strings.

Il utilise fortement la conversion implicite, ce qui explique pourquoi il peut sembler plus compact.

Il suppose également que seuls les trois formats mentionnés dans votre question sont utilisés. S'il y a une valeur avec un format "invalide", cela va casser cette solution.

 SELECT CASE WHEN PageNo NOT LIKE '%[^0-9]%' THEN PageNo WHEN PageNo LIKE '%[AZ]' THEN LEFT(PageNo, LEN(PageNo) - 1) + (ASCII(RIGHT(PageNo, 1)) - 64) * 0.01 WHEN PageNo LIKE '%-%' THEN REPLACE(PageNo, '-', '.') * 1.0 + 0.26 END FROM ... 

C'est moche et probablement pas très performant, mais:

 select page_num, case when page_num like '%A' then subssortingng(page_num, 1, len(page_num)-1) + '.01' when page_num like '%B' then subssortingng(page_num, 1, len(page_num)-1) + '.02' when page_num like '%C' then subssortingng(page_num, 1, len(page_num)-1) + '.03' when page_num like '%D' then subssortingng(page_num, 1, len(page_num)-1) + '.04' when page_num like '%E' then subssortingng(page_num, 1, len(page_num)-1) + '.05' when page_num like '%F' then subssortingng(page_num, 1, len(page_num)-1) + '.06' when page_num like '%G' then subssortingng(page_num, 1, len(page_num)-1) + '.07' when page_num like '%H' then subssortingng(page_num, 1, len(page_num)-1) + '.08' when page_num like '%I' then subssortingng(page_num, 1, len(page_num)-1) + '.09' when page_num like '%J' then subssortingng(page_num, 1, len(page_num)-1) + '.10' when page_num like '%K' then subssortingng(page_num, 1, len(page_num)-1) + '.11' when page_num like '%L' then subssortingng(page_num, 1, len(page_num)-1) + '.12' when page_num like '%M' then subssortingng(page_num, 1, len(page_num)-1) + '.13' when page_num like '%N' then subssortingng(page_num, 1, len(page_num)-1) + '.14' when page_num like '%O' then subssortingng(page_num, 1, len(page_num)-1) + '.15' when page_num like '%P' then subssortingng(page_num, 1, len(page_num)-1) + '.16' when page_num like '%Q' then subssortingng(page_num, 1, len(page_num)-1) + '.17' when page_num like '%R' then subssortingng(page_num, 1, len(page_num)-1) + '.18' when page_num like '%S' then subssortingng(page_num, 1, len(page_num)-1) + '.19' when page_num like '%T' then subssortingng(page_num, 1, len(page_num)-1) + '.20' when page_num like '%U' then subssortingng(page_num, 1, len(page_num)-1) + '.21' when page_num like '%V' then subssortingng(page_num, 1, len(page_num)-1) + '.22' when page_num like '%W' then subssortingng(page_num, 1, len(page_num)-1) + '.23' when page_num like '%X' then subssortingng(page_num, 1, len(page_num)-1) + '.24' when page_num like '%Y' then subssortingng(page_num, 1, len(page_num)-1) + '.25' when page_num like '%Z' then subssortingng(page_num, 1, len(page_num)-1) + '.26' when page_num like '%-%' then subssortingng(page_num, 1, charindex('-', page_num)-1) + '.' + cast((26+cast(subssortingng(page_num, charindex('-', page_num)+1, len(page_num)) as int)) as varchar(12)) else page_num + '.00' end from pages 

Voir SQL Fiddle pour le schéma complet que je testais.

Cela dit, je vous recommand fortement de mettre à jour votre schéma avec quelque chose qui inclut les numéros de page normalisés et de convertir ceci en path dans la table.