1
votes

SQL: Comment diviser une colonne par nombre de caractères

J'ai une colonne avec des lettres. Je veux diviser cette colonne en morceaux de trois. De quel code SQL pour Microsoft aurais-je besoin? J'ai lu `` diviser mon caractère spécial '' mais je ne sais pas comment créer une division par valeur où la division n'est pas non plus limitée au nombre de colonnes.

entrez la description de l'image ici


0 commentaires

3 Réponses :


1
votes

Vous pouvez faire:

select t.*, substring(col, 1, 3), substring(col, 4, 3), substring(col, 7, 3) 
from table t


0 commentaires

1
votes

Si vous voulez vraiment faire cela de manière dynamique, comme indiqué dans la question, et que vous avez une requête qui crée autant de colonnes que nécessaire, alors vous avez besoin de SQL dynamique.

Voici une solution qui utilise un CTE récusif pour générer la chaîne de requête.

-- debug
| sql                                                                                                                                 |
| :---------------------------------------------------------------------------------------------------------------------------------- |
| select substring(code, 1, 3) col1, substring(code, 4, 3) col2, substring(code, 7, 3) col3, substring(code, 10, 3) col4 from mytable |

-- results
col1 | col2 | col3 | col4
:--- | :--- | :--- | :---
ABC  | DEF  | GHI  |     
XYZ  | ABC  |      |     
JKL  | MNO  | PQR  | STU 
ABC  | DEF  |      |     

L'ancre de la requête récursive calcule la longueur de la chaîne la plus longue dans la colonne code . Ensuite, la partie récursive génère une série d'expressions substring () pour chaque morceau de 3 caractères, avec des noms de colonnes dynamiques comme col1 , col2 et bientôt. Vous pouvez ensuite (déboguer et) exécuter cette chaîne de requête.

Démo sur DB Fiddle :

declare @sql nvarchar(max);

with cte as (
    select 
        1 pos, 
        cast('substring(code, 1, 3) col1' as nvarchar(max)) q, 
        max(len(code)) max_pos from mytable
    union all 
    select 
        pos + 1, 
        cast(
            q 
            + ', substring(code, ' + cast(pos * 3 + 1 as nvarchar(3)) 
            + ', 3) col' 
            + cast(pos + 1 as nvarchar(3)) 
        as nvarchar(max)), 
        max_pos
    from cte
    where pos < max_pos / 3
)
select @sql = N'select ' + q + ' from mytable' 
from cte 
where len(q) = (select max(len(q)) from cte);

select @sql sql;
EXEC sp_executesql @sql;


0 commentaires

0
votes

Essayez-le comme ceci, qui ne nécessite aucun SQL générique (tant que vous pouvez spécifier un nombre maximum de colonnes):

Nous devons d'abord définir un scénario de maquette pour simuler votre issue

SELECT p.*
FROM
(
    SELECT t.ID
          ,CONCAT('Col',A.Nmbr) AS ColumnName
          ,SUBSTRING(t.YourString,(A.Nmbr-1)*@ChunkLength + 1,@ChunkLength) AS Chunk
    FROM @tbl t
    CROSS APPLY
    (
        SELECT TOP((LEN(t.YourString)+(@ChunkLength-1))/@ChunkLength) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values
    ) A(Nmbr)
) src   
PIVOT
(
    MAX(Chunk) FOR ColumnName IN(Col1,Col2,Col3,Col4,Col5,Col6 /*add the maximum column count here*/)
) p;                    

- Nous pouvons définir la longueur du morceau de manière générique. Essayez-le avec d'autres valeurs ...

DECLARE @ChunkLength INT=3;

--La requête

DECLARE @tbl TABLE(ID INT IDENTITY, YourString VARCHAR(100));
INSERT INTO @tbl VALUES ('AB')
                       ,('ABC') 
                       ,('ABCDEFGHI') 
                       ,('XYZABC') 
                       ,('JKLMNOPQRSTU') 
                       ,('ABCDEF');

L'idée en bref: p >

  • En utilisant un appel APPLY , nous pouvons créer un décompte par ligne . Cela renverra plusieurs lignes par chaîne d'entrée. Le nombre de lignes est défini par la clause TOP calculée.
  • Nous utilisons le décompte par ligne d'abord pour créer un nom de colonne et ensuite comme paramètres dans SUBSTRING () .
  • Enfin, nous pouvons utiliser PIVOT pour renvoyer ceci sous forme de liste horizontale.

Un indice sur les ensembles de résultats génériques:

Cela pourrait être une sorte de religion , mais - du moins à mon avis - je préférerais un fix avec beaucoup de colonnes vides, plutôt qu'un ensemble défini de manière générique . Le consommateur doit connaître le format du résultat à l'avance ...

Vous pouvez utiliser exactement la même requête qu'une instruction SQL créée dynamiquement. La seule chose que vous auriez besoin de changer est la liste réelle des noms de colonnes dans la clause IN du PIVOT.


0 commentaires