Dans SQL Server, j'ai un champ contenant des données délimitées (par un espace).
Ex.
2|1 2 3 3 5 3|1 1 1 1 1
Je dois parcourir tous les enregistrements du DB et interrogez le champ de données délimité et comparez les troisième et quatrième parties de données les unes par rapport aux autres et si elles correspondent, retournez le recid et le champ délimité entier.
Donc, d'après mon exemple, les enregistrements 2 et 3 ont une correspondance parties de données, donc il renverrait: -
recid| Delimited data field 1| 1 2 3 4 5 2| 1 2 3 3 5 3| 1 1 1 1 1
Parce que 3 3 correspond, tout comme 1 1.
Merci.
p >
6 Réponses :
S'il s'agit toujours d'un chiffre et du même format, vous pouvez essayer comme suit.
;WITH cte AS (SELECT F1.recid, F1.[data], O.splitdata, Row_number() OVER( partition BY recid ORDER BY (SELECT 1)) rn FROM (SELECT *, Cast('<X>' + Replace(F.data, ' ', '</X><X>') + '</X>' AS XML) AS xmlfilter FROM @table F)F1 CROSS apply (SELECT fdata.d.value('.', 'varchar(50)') AS splitdata FROM f1.xmlfilter.nodes('X') AS fdata(d)) O) SELECT c1.recid, c1.data FROM cte c1 INNER JOIN cte c2 ON c1.recid = c2.recid AND c1.rn = 3 AND c2.rn = 4 AND c1.splitdata = c2.splitdata GROUP BY c1.recid, c1.data
Sinon (les nombres ne sont pas à un seul chiffre), vous pouvez essayer comme suit.
select * from @table where SUBSTRING([data], 5, 1) = SUBSTRING([data], 7, 1)
Cela suppose que les données délimitées ne comportent qu'un seul caractère. Cela pourrait être une hypothèse de coût.
@Larnu, je suis d'accord, c'est pourquoi j'ai mentionné dans la réponse. Je mettrai à jour pour l'approche différente
Je sais, mais je soupçonne qu'il est très peu probable que les valeurs ne soient que 0-9
.
@Larnu, j'ai également mis à jour la réponse pour l'autre scénario.
Excellent merci beaucoup @PSK comment pourrais-je récupérer les 4 premiers numéros de ligne. par exemple 1 2 3 3 1 1 1 1?
Je suis désolé de ne pas comprendre votre question, pouvez-vous l'expliquer plus en détail.
donc si j'avais `` 1 22 33 33 44 '' et que cela correspond à `` 33 33 '', comment pourrais-je sélectionner uniquement les 3 premières parties de la colonne, par exemple «1 22 33»?
pouvez-vous vérifier cela rextester.com/KMX12033 , vous pouvez également voter pour la réponse si vous le souhaitez :)
Il faut diviser les données, donner le numéro de ligne, puis comparer.
Schéma:
recid Delimited_data_field 2 1 2 3 3 5 3 1 1 1 1 1
Solution:
;WITH CTE AS ( SELECT recid ,Delimited_data_field ,ROW_NUMBER() OVER (PARTITION BY recid ORDER BY (SELECT 1)) RNO ,splt.X.value('.', 'INT') VAL FROM ( SELECT recid ,Delimited_data_field ,CAST('<M>' + REPLACE(Delimited_data_field, ' ', '</M><M>') + '</M>' AS XML) DATA FROM #TAB ) A CROSS APPLY A.DATA.nodes('/M') splt(x) ) SELECT C.recid ,C2.Delimited_data_field FROM CTE C INNER JOIN CTE C2 ON C.recid = C2.recid AND C.RNO = 3 AND C2.RNO = 4 AND C.VAL = C2.VAL
Résultat:
SELECT * INTO #TAB FROM ( SELECT 1, '1 2 3 4 5' UNION ALL SELECT 2, '1 2 3 3 5' UNION ALL SELECT 3, '1 1 1 1 1' )A (recid , Delimited_data_field)
J'ai posté exactement la même réponse avant vous :)
Oui .. exactement la même chose .. :) @PSK
Votre question comprend deux parties: trouvez la nième division, puis comparez. Votre première approche devrait être de résoudre le problème jusqu'à ce que vous trouviez des fonctions intégrées capables de faire le travail. voici une méthode qui renvoie le résultat de la requête interne après la séparation et les comparaisons externes:
SELECT recid,Delimited from ( SELECT recid,Delimited, SUBSTRING(Delimited, charindex(' ', Delimited, (charindex(' ', Delimited, 1))+2)+1,1) third, SUBSTRING(Delimited, charindex(' ',Delimited, (charindex(' ', Delimited, 1))+3)+1,1) fourth FROM YourTable) tr WHERE third = fourth
Voir une sous-chaîne
simple et charindex
peuvent faire le travail.
Voici une autre solution à cela.
J'ai modifié la fonction de fractionnement dans ce lien ( T-SQL: Opposé à la concaténation de chaînes - comment diviser une chaîne en plusieurs enregistrements ) un peu pour le rendre utile dans votre scénario. p>
Voici la fonction.
select recid, deldata from so1 where dbo.SplitAndGetNumberAt (' ', deldata, 3) = dbo.SplitAndGetNumberAt (' ', deldata, 4)
Vous pouvez maintenant utiliser cette fonction pour obtenir la 3e et 4e position des nombres et comparer facilement.
CREATE FUNCTION dbo.SplitAndGetNumberAt (@sep char(1), @s varchar(512), @pos int) RETURNS INT BEGIN declare @val as varchar(10); WITH Pieces(pn, start, stop) AS ( SELECT 1, 1, CHARINDEX(@sep, @s) UNION ALL SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1) FROM Pieces WHERE stop > 0 ) SELECT @val = SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) FROM Pieces where pn = @pos; RETURN @val END
J'espère que cela vous aidera.
Si vous disposez de SQL Server 2016 ou version ultérieure, vous pouvez essayer une approche utilisant OPENJSON ()
pour fractionner vos données d'entrée. La partie importante ici est le fait que lorsque OPENJSON analyse un tableau JSON, les index des éléments dans le texte JSON sont renvoyés sous forme de clés (basé sur 0).
Entrée:
RecId Data 2 1 2 3 3 5 3 1 1 1 1 1
Juste pour le plaisir, une sorte de codage fou:
DECLARE @Table Table ( recid INT, DelimitedDataField VARCHAR(32) ) INSERT @Table (recid, DelimitedDataField) VALUES (1, '1 2 3 4 5'), (2, '1 2 3 3 5'), (3, '1 1 1 1 1') SELECT * FROM @Table WHERE SUBSTRING ( STUFF( STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '' ), 1, CHARINDEX(' ', STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '') ), ''), 1, CHARINDEX(' ', STUFF( STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '' ), 1, CHARINDEX(' ', STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '') ), '') ) ) = SUBSTRING ( STUFF( STUFF( STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '' ), 1, CHARINDEX(' ', STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '') ), ''), 1, CHARINDEX(' ', STUFF( STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '' ), 1, CHARINDEX(' ', STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '') ), '') ), '' ), 1, CHARINDEX(' ', STUFF( STUFF( STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '' ), 1, CHARINDEX(' ', STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '') ), ''), 1, CHARINDEX(' ', STUFF( STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '' ), 1, CHARINDEX(' ', STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '') ), '') ), '' )) ) AND SUBSTRING ( STUFF( STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '' ), 1, CHARINDEX(' ', STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '') ), ''), 1, CHARINDEX(' ', STUFF( STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '' ), 1, CHARINDEX(' ', STUFF( DelimitedDataField + ' - - -', 1, CHARINDEX(' ', DelimitedDataField + ' - - -'), '') ), '') ) ) <>'-'
Corrigez votre modèle de données! Vous ne devez pas stocker de nombres sous forme de chaînes. Vous ne devez pas non plus stocker plusieurs valeurs dans une seule colonne. Je ferais l'effort de corriger les données plutôt que d'essayer de résoudre ce problème.
Vos données sont-elles toujours en 5 parties? Serait-ce moins / plus? Qu'avez-vous essayé? (Gordan a raison cependant, vous devriez réparer votre structure, si vous pouvez le faire, les bénévoles ici se feront un plaisir de vous montrer comment.)
Les tables ont des colonnes , pas des champs.
Et ce ne sont pas des lignes des enregistrements.