Je souhaite scinder certaines données sur la base d'un délimiteur qui peut exister ou non.
Exemple de données:
John/Smith
Jane/Doe
Steve
Bob/Johnson
J'utilise le code suivant pour scinder ces données en noms et prénoms:
SELECT SUBSTRING(myColumn, 1, CHARINDEX('/', myColumn)-1) AS FirstName,
SUBSTRING(myColumn, CHARINDEX('/', myColumn) + 1, 1000) AS LastName
FROM MyTable
Les résultats que je voudrais:
FirstName---LastName
John--------Smith
Jane--------Doe
Steve-------NULL
Bob---------Johnson
Ce code fonctionne très bien tant que toutes les lignes ont le délimiteur anticipé, mais il y a erreur quand une ligne ne le fait pas:
"Invalid length parameter passed to the LEFT or SUBSTRING function."
Comment une réécriture peut-elle fonctionner correctement?
Peut-être que cela vous aidera.
SELECT SUBSTRING(myColumn, 1, CASE CHARINDEX('/', myColumn)
WHEN 0
THEN LEN(myColumn)
ELSE CHARINDEX('/', myColumn) - 1
END) AS FirstName
,SUBSTRING(myColumn, CASE CHARINDEX('/', myColumn)
WHEN 0
THEN LEN(myColumn) + 1
ELSE CHARINDEX('/', myColumn) + 1
END, 1000) AS LastName
FROM MyTable
Pour ceux qui recherchent des réponses à SQL Server 2016+. Utilisez la fonction STRING_SPLIT intégrée
Par exemple:
DECLARE @tags NVARCHAR(400) = 'clothing,road,,touring,bike'
SELECT value
FROM STRING_SPLIT(@tags, ',')
WHERE RTRIM(value) <> '';
Référence: https://msdn.Microsoft.com/en-nz/library/mt684588.aspx
CHOISIR LE CAS WHEN CHARINDEX ('/', maColonne, 0) = 0 PUIS ma colonne ELSE LEFT (myColumn, CHARINDEX ('/', myColumn, 0) -1) END AS Prénom ,CAS WHEN CHARINDEX ('/', maColonne, 0) = 0 PUIS '' ELSE RIGHT (myColumn, CHARINDEX ('/', REVERSE (myColumn), 0) -1) END AS LastName FROM MyTable
Essayez de filtrer les lignes qui contiennent des chaînes avec le délimiteur et travaillez sur celles-ci uniquement:
SELECT SUBSTRING(myColumn, 1, CHARINDEX('/', myColumn)-1) AS FirstName,
SUBSTRING(myColumn, CHARINDEX('/', myColumn) + 1, 1000) AS LastName
FROM MyTable
WHERE CHARINDEX('/', myColumn) > 0
Ou
SELECT SUBSTRING(myColumn, 1, CHARINDEX('/', myColumn)-1) AS FirstName,
SUBSTRING(myColumn, CHARINDEX('/', myColumn) + 1, 1000) AS LastName
FROM MyTable
WHERE myColumn LIKE '%/%'
ALTER FUNCTION [dbo].[split_string](
@delimited NVARCHAR(MAX),
@delimiter NVARCHAR(100)
) RETURNS @t TABLE (id INT IDENTITY(1,1), val NVARCHAR(MAX))
AS
BEGIN
DECLARE @xml XML
SET @xml = N'<t>' + REPLACE(@delimited,@delimiter,'</t><t>') + '</t>'
INSERT INTO @t(val)
SELECT r.value('.','varchar(MAX)') as item
FROM @xml.nodes('/t') as records(r)
RETURN
END
Les exemples ci-dessus fonctionnent bien lorsqu'il n'y a qu'un seul délimiteur, mais ils ne s'adaptent pas bien à plusieurs délimiteurs. Notez que cela ne fonctionnera que pour SQL Server 2016 et versions ultérieures.
/*Some Sample Data*/
DECLARE @mytable TABLE ([id] VARCHAR(10), [name] VARCHAR(1000));
INSERT INTO @mytable
VALUES ('1','John/Smith'),('2','Jane/Doe'), ('3','Steve'), ('4','Bob/Johnson')
/*Split based on delimeter*/
SELECT P.id, [1] 'FirstName', [2] 'LastName', [3] 'Col3', [4] 'Col4'
FROM(
SELECT A.id, X1.VALUE, ROW_NUMBER() OVER (PARTITION BY A.id ORDER BY A.id) RN
FROM @mytable A
CROSS APPLY STRING_SPLIT(A.name, '/') X1
) A
PIVOT (MAX(A.[VALUE]) FOR A.RN IN ([1],[2],[3],[4],[5])) P