2017-04-19 4 views
0

Ich habe das folgende Snippet online gefunden:Finden längstes Wort in Zeichenfolge mit SQL

DECLARE @str VARCHAR(5000)= 'aaaa bbbbb cccccccc ddddddddddddddddddd' 

SELECT TOP 1 Split.a.value('.', 'VARCHAR(100)') as longest_Word 
FROM (SELECT Cast ('<M>' + Replace(@str, ' ', '</M><M>') + '</M>' AS XML) AS Data) AS A 
     CROSS APPLY Data.nodes ('/M') AS Split(a) 
ORDER BY Len(Split.a.value('.', 'VARCHAR(100)')) DESC 

, die das längste Wort in einer Textdatei ("in diesem Fall ddddddddddddddddddd) findet. Ich weiß jedoch nicht, wie ich dies pro Zeile in einer bestimmten Spalte anwenden soll, so dass es eine Spalte neben jeder Zeile hinzufügt, die mir sagt, was das längste Wort in SQL Server ist.

Jede Spalte in SQL Server, in dem es so aussehen mit der zusätzlichen Spalte gesucht werden muss sollte neben hinzugefügt:

COLUMN 1  RESULT 
ABC ABCD  ABCD 
BC BCDE  BCDE 
9II IIIIV IIIIV 
...   ... 
+2

Was machen Sie für Krawatten? – SqlZim

+0

@SqlZim Guter Punkt. Ich werde auf die Antwort von OP achten. –

+0

@ JohnCappelletti Ich war nur neugierig. Ihre Antwort wurde bereits aktualisiert, da es unabhängig von der Antwort eine geringfügige Anpassung ist. – SqlZim

Antwort

2

Ein einfaches CROSS APPLY hier helfen können.

Hinweis, habe ich meinen eigenen XML-Parser, weil es "XML-Safe" ist

Declare @YourTable table ([COLUMN 1] varchar(max)) 
Insert Into @YourTable values 
('ABC ABCD'), 
('BC BCDE'), 
('9II IIIIV') 

Select A.[COLUMN 1] 
     ,Result = B.RetVal 
From @YourTable A 
Cross Apply (
       Select Top 1 * 
       From (
         Select RetSeq = Row_Number() over (Order By (Select null)) 
           ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)'))) 
         From (Select x = Cast('<x>' + replace((Select replace(A.[COLUMN 1],' ','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
         Cross Apply x.nodes('x') AS B(i) 
         ) B1 
       Order by Len(RetVal) Desc,RetSeq 
      ) B 

Returns

COLUMN 1 Result 
ABC ABCD ABCD 
BC BCDE BCDE 
9II IIIIV IIIIV 

EDIT - Sie wollen TIES

zeigen
Declare @YourTable table ([COLUMN 1] varchar(max)) 
Insert Into @YourTable values 
('ABC ABCD'), 
('BC BCDE 1234'), 
('9II IIIIV') 

Select A.[COLUMN 1] 
     ,Result = B.RetVal 
From @YourTable A 
Cross Apply (
       Select Top 1 with ties * 
       From (
         Select RetSeq = Row_Number() over (Order By (Select null)) 
           ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)'))) 
         From (Select x = Cast('<x>' + replace((Select replace(A.[COLUMN 1],' ','§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A 
         Cross Apply x.nodes('x') AS B(i) 
         ) B1 
       Order by Dense_Rank() over (Order by Len(RetVal) Desc) 
      ) B 

Rückgabe

COLUMN 1  Result 
ABC ABCD  ABCD 
BC BCDE 1234 BCDE --<< Tie 
BC BCDE 1234 1234 --<< Tie Added for Illustration 
9II IIIIV  IIIIV 
+0

Das sieht gut aus. Ein kleinerer Kommentar ist, dass, wo die Felder Satzzeichen wie Kommas, ganze Punkte und Klammern enthalten, dieser Code sie effektiv als Teil eines Wortes behandelt, das sie als Nachbarn haben. Um dies zu vermeiden, können Sie vor dem Anwenden der obigen Logik jedes anstößige Interpunktionszeichen durch ein Leerzeichen ersetzen. Auch wenn das mit einigen Zeichen umständlich sein könnte - wie zum Beispiel Apostrophe, die sowohl innerhalb als auch außerhalb von Wörtern existieren können. –

+0

@SteveLovell True, aber OP erwähnte keine Interpunktion. Wenn dies der Fall ist, gibt es andere Techniken, um die Zeichenfolge zu "normalisieren". Für den Moment nehme ich es auf den Nennwert der Raumbegrenzung –

+0

Danke für die Hilfe John, aber dies ist immer noch auf ein Beispiel Ihrer eigenen Eingabe basiert. Ich würde das gerne auf eine bestehende Tabelle mit einer bestehenden Spalte anwenden. Aber das Ersetzen von @yourtable durch meinen Tabellennamen funktioniert nicht und das Gleiche gilt für den Spaltennamen. – Probs

Verwandte Themen