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.