3
votes

Comment convertir 119.305.1983984.1 en 1.1983984.305.119 en serveur SQL?

Je dois convertir 119.305.1983984.1 en 1.1983984.305.119 dans SQL Server.

J'ai essayé comme indiqué ci-dessous en utilisant reverse , mais cela ne fonctionne pas

DECLARE @myvar varchar(20);  
SET @myvar = '119.305.1983984.1';  
SELECT REVERSE(@myvar) AS Reversed ;  
GO  

Le résultat est 1.4893891.503.911
Le résultat attendu est 1.1983984.305.119

Je ne veux pas être inversé.


8 commentaires

Pourquoi déclarez-vous la variable comme varchar (10) et attribuez-vous plus de 10 caractères?


D'abord vous dites que vous voulez passer de 305.1983984.1 à 1.1983984.305.119, puis le code a 119.305.1983984.1 ...


je veux écrire du dernier au premier 1.1983984.305.119 du premier au dernier: 119.305.1983984.1 du dernier au premier: 1.1983984.305.119


C'est vraiment quelque chose de mieux géré dans votre application / couche externe. Vous essayez de faire une manipulation complexe de ce qui devrait idéalement être un point unique de données quelque peu immuable dans SQL Server.


Le nombre de pièces est-il constant et le séparateur est-il toujours un point? Il se trouve que vous pouvez abuser de PARSENAME pour: SELECT CONCAT (PARSENAME (@myvar, 1), '.', PARSENAME (@myvar, 2), '.', PARSENAME ( @myvar, 3), '.', PARSENAME (@myvar, 4)) (en supposant que vous atteignez la longueur de @myvar pour qu'il puisse effectivement contenir la chaîne, bien sûr).


Essayez quelque chose en utilisant la fonction STRING_SPLIT en passant un point comme séparateur


@RobertKock Il n'y a aucun moyen avec string_split de garantir l'ordre des morceaux. Lorsque vous le recollerez, il n'y aura pas de colonne à commander.


@GSerg vous avez raison. J'ai raté cette partie. Oublie mon commentaire


4 Réponses :


1
votes
+-------------------+
| 1.1983984.305.119 |
+-------------------+

1 commentaires

non je veux obtenir 1.1983984.305.119 mais ce code 1.4893891.503.911



1
votes

Si le nombre de jetons est connu et qu'il est jusqu'à quatre (SQL Server 2012+) :

DECLARE @myvar varchar(20), @separator CHAR(1)  
SET @myvar = '119.305.1983984.1';  
SET @separator = '.'


SELECT STRING_AGG(value, @separator)  WITHIN GROUP ( ORDER BY rn DESC ) 
FROM (
    SELECT value, ROW_NUMBER() OVER (ORDER BY (SELECT 0) ) rn
    FROM STRING_SPLIT ( @myvar , @separator )  
) d OPTION (MAXDOP 1)

Valeur d'origine: 119.305.1983984.1

SELECT renvoie: 1.1983984.305.119


Si le nombre de jetons varie et que SQL Server est 2017+:

DECLARE @myvar varchar(20);  
SET @myvar = '119.305.1983984.1';  

SELECT CONCAT(PARSENAME(@myvar,1),'.',PARSENAME(@myvar,2),'.',PARSENAME(@myvar,3),'.',PARSENAME(@myvar,4)) 

SELECT renvoie: 1.1983984.305.119


7 commentaires

Cela doit s'accompagner de mises en garde: le nombre de parties doit être exactement 4, le séparateur doit être un point et les parties ne peuvent pas inclure les caractères spéciaux [, ] ou ". S'écarter de tout cela fera échouer cela de manière plus ou moins intéressante.


Je pense que OP veut inverser la chaîne entière et votre requête fonctionnera uniquement pour un nombre défini de points (.). Il ne s'inversera pas dans les deux cas lorsque le nombre de points (.) Augmente ou diminue. De plus, il ne fonctionnera pas dans la version inférieure de SQL Server, mais ce n'est pas un cas.


@Suraj: PARSENAME est disponible depuis au moins SQL Server 2005 (et je suis presque sûr qu'il est en fait plus ancien que cela). CONCAT n'est disponible que depuis SQL Server 2012, mais l'utilisation ici est facultative - + fonctionne tout aussi bien. Quels que soient les autres problèmes de cette approche, la compatibilité n'en fait pas partie.


@JeroenMostert Comme nous l'avons déjà mentionné, Concat ne fonctionne pas, mais ce n'est pas un problème déjà écrit, mais lorsque le nombre de points augmentera ou diminuera, cela ne fonctionnera pas correctement.


@JeroenMostert, en effet le nombre de jetons devrait être jusqu'à 4 pour tirer parti du parsename. SQL Server 2017 offre plus d'options pour obtenir le résultat souhaité de manière plus ou moins élégante.


Il convient probablement de noter que si en réalité vous allez probablement obtenir le résultat attendu avec le order by (select 0) , il n'est pas réellement garanti, et il est théoriquement possible qu'en raison de bizarreries de mise en œuvre / parallélisme les morceaux ne seront pas numérotés dans l'ordre prévu.


@GSerg, merci, bon point, sur de grands ensembles de données, cela peut être un cas. La requête est ajustée, MAXDOP 1 ajouté



0
votes

Vous pouvez essayer la requête suivante comme indiqué ci-dessous. Cela exécutera toutes les versions du serveur SQL et il n'est pas nécessaire de transmettre une valeur matérielle telle que 1, 2 ou n pour la position.

Declare @test varchar(max)
Set @test = '119.305.1983984.1'

DECLARE @listStr VARCHAR(MAX)
SELECT @listStr = COALESCE(@listStr+'.' ,'') + Convert(Varchar(10), IpAddress)
from (
Select 
   ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) RN,  T2.item.value('(./text())[1]','int') as IpAddress
from
     (select convert(xml,'<items><t>'+replace(@test,'.','</t><t>')+'</t></items>') as xmldoc)
as xmltable
     CROSS APPLY xmltable.xmldoc.nodes('/items/t') as T2(item)      
)a order by RN desc

select @listStr


0 commentaires

0
votes

Vous pouvez créer une fonction de fractionnement via un délimiteur (.) . Ensuite, toutes les valeurs se transforment en table. Par la fonction ROW_NUMBER (), vous pouvez définir un nombre avec tous les éléments pour les INVERSER. Enfin, vous pouvez utiliser COALESCE pour les concaténer.

fonction de fractionnement

DECLARE @myvar varchar(20);  
SET @myvar = '119.305.1983984.1';
Declare @val Varchar(MAX);
Select @val = COALESCE(@val + '.' + Value, Value) 
FROM 
    (
        SELECT Value,ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as number from [dbo].[Split]('.',@myvar)
    ) AS T ORDER BY number DESC
SELECT @val;

Requête OUTPUT

CREATE FUNCTION [dbo].[Split](@Delimiter varchar(5), @List varchar(8000) ) 
RETURNS @TableOfValues table 
(  Value varchar(50)   ) 
AS 
BEGIN

DECLARE @LenString int 

WHILE len( @List ) > 0 
    BEGIN 

    SELECT @LenString = 
        (CASE charindex( @Delimiter, @List ) 
            WHEN 0 THEN len( @List ) 
            ELSE ( charindex( @Delimiter, @List ) -1 )
        END
        ) 

    INSERT INTO @TableOfValues 
        SELECT substring( @List, 1, @LenString )

    SELECT @List = 
        (CASE ( len( @List ) - @LenString ) 
            WHEN 0 THEN '' 
            ELSE right( @List, len( @List ) - @LenString - 1 ) 
        END
        ) 
    END
    RETURN 
END 

SORTIE 1.1983984.305.119


0 commentaires