Ich bin ein Anfänger in T-SQL. Ich möchte entscheiden, ob eine Eingabezeichenfolge ein Palindrom ist, mit output = 0, wenn dies nicht der Fall ist, und output = 1, wenn dies der Fall ist. Ich finde immer noch die Syntax heraus. Ich erhalte nicht einmal eine Fehlermeldung. Ich suche nach verschiedenen Lösungen und ein paar Rückmeldungen, um besser zu verstehen und zu verstehen, wie T-SQL funktioniert, um besser darin zu werden - ich bin noch Student.
Die Schlüsselidee, wie ich es sehe, ist es, die Zeichen ganz links und ganz rechts miteinander zu vergleichen, auf Gleichheit zu prüfen und dann das zweite Zeichen von links mit dem zweitletzten zu vergleichen usw. Wir machen eine Schleife: Wenn die Zeichen gleich sind, fahren wir fort. Wenn wir das Ende erreicht haben, geben wir 1 aus, wenn nicht, geben wir 0 aus.
Würden Sie bitte kritisieren:
CREATE function Palindrome(
@String Char
, @StringLength Int
, @n Int
, @Palindrome BIN
, @StringLeftLength Int
)
RETURNS Binary
AS
BEGIN
SET @ n=1
SET @StringLength= Len(String)
WHILE @StringLength - @n >1
IF
Left(String,@n)=Right(String, @StringLength)
SET @n =n+1
SET @StringLength =StringLength -1
RETURN @Binary =1
ELSE RETURN @Palindrome =0
END
Ich glaube, ich bin auf dem richtigen Weg, aber ich bin noch weit weg. Irgendwelche Ideen?
LTRIM(RTRIM(...))
Leerzeichen?Antworten:
Wenn Sie SQL Server verwenden, können Sie mit der Funktion REVERSE () überprüfen, ob?
Mit dem Kommentar von Martin Smith können Sie in SQL Server 2012+ die IIF () -Funktion verwenden:
quelle
Da es eine ganze Reihe von Lösungen gibt, werde ich mich mit dem "Kritik" -Teil Ihrer Frage befassen. Ein paar Anmerkungen: Ich habe einige Tippfehler behoben und festgestellt, wo ich sie gemacht habe. Wenn ich mich geirrt habe, erwähne ich es in den Kommentaren und erkläre, was los ist. Ich werde auf einige Dinge hinweisen, die Sie vielleicht bereits wissen, nehmen Sie sich also bitte keine Sorgen, wenn ich es tue. Einige Kommentare mögen wählerisch erscheinen, aber ich weiß nicht, wo Sie sich auf Ihrer Reise befinden, also müssen Sie davon ausgehen, dass Sie gerade erst anfangen.
Schließen Sie IMMER die Länge mit einem
char
oder einervarchar
Definition ein. Aaron Bertrand spricht hier ausführlich darüber . Er redet,varchar
aber das gilt auchchar
. Ich würde dafür eine verwenden,varchar(255)
wenn Sie nur relativ kurze Zeichenfolgen oder vielleicht einevarchar(8000)
für größere oder sogar möchtenvarchar(max)
.Varchar
ist für Zeichenfolgen mit variabler Längechar
nur für feste Zeichenfolgen . Da Sie nicht sicher sind, wie lange die Zeichenfolge verwendet wirdvarchar
. Auch ist esbinary
nichtbin
.Als Nächstes müssen Sie nicht alle diese Variablen als Parameter angeben. Deklarieren Sie sie in Ihrem Code. Nehmen Sie etwas nur in die Parameterliste auf, wenn Sie es weitergeben möchten. (Sie werden sehen, wie dies am Ende aussieht.) Sie haben auch @StringLeftLength, verwenden es aber nie. Also werde ich es nicht erklären.
Das nächste, was ich tun werde, ist ein bisschen neu zu formatieren, um ein paar Dinge klar zu machen.
Wenn Sie sich die Art und Weise ansehen, wie ich die Einrückung vorgenommen habe, werden Sie feststellen, dass ich Folgendes habe:
Das ist , weil Befehle wie
WHILE
undIF
nur die erste Zeile des Codes nach ihnen beeinflussen. Sie müssen einenBEGIN .. END
Block verwenden, wenn Sie mehrere Befehle wünschen. So fixierend, dass wir bekommen:Sie werden bemerken, dass ich nur einen
BEGIN .. END
Block in den Ordner eingefügt habeIF
. Das liegt daran, dass dieIF
Anweisung, obwohl sie mehrere Zeilen lang ist (und sogar mehrere Befehle enthält), immer noch eine einzelne Anweisung ist (die alles abdeckt, was inIF
und in denELSE
Teilen der Anweisung ausgeführt wird).Als nächstes erhalten Sie nach beiden eine Fehlermeldung
RETURNs
. Sie können eine Variable ODER ein Literal zurückgeben. Sie können die Variable nicht gleichzeitig setzen und zurückgeben.Jetzt sind wir in der Logik. Lassen Sie mich zunächst darauf hinweisen, dass die
LEFT
undRIGHT
Funktionen, die Sie verwenden, großartig sind, aber Ihnen die Anzahl der Zeichen geben werden, die Sie aus der angeforderten Richtung übergeben. Angenommen, Sie haben das Wort "Test" bestanden. Beim ersten Durchgang erhalten Sie Folgendes (Entfernen von Variablen):Offensichtlich haben Sie das nicht erwartet. Sie würden wirklich
substring
stattdessen verwenden möchten . Mit der Teilzeichenfolge können Sie nicht nur den Startpunkt, sondern auch die Länge eingeben. So würden Sie erhalten:Als nächstes erhöhen Sie die Variablen, die Sie in Ihrer Schleife verwenden, nur in einer Bedingung der IF-Anweisung. Ziehen Sie die Variableninkrementierung vollständig aus dieser Struktur heraus. Das erfordert einen zusätzlichen
BEGIN .. END
Block, aber ich muss den anderen entfernen.Sie müssen Ihren
WHILE
Zustand ändern , um den letzten Test durchführen zu können.Und last but not least, wie es jetzt aussieht, testen wir nicht das letzte Zeichen, wenn es eine ungerade Anzahl von Zeichen gibt. Zum Beispiel mit 'ana' wird das
n
nicht getestet. Das ist in Ordnung, aber es tut mir leid, dass wir ein einzelnes Buchstabenwort berücksichtigen müssen (wenn Sie möchten, dass es als positiv gilt). Das können wir also tun, indem wir den Wert im Voraus festlegen.Und jetzt haben wir endlich:
Ein letzter Kommentar. Ich bin ein großer Fan von Formatierung im Allgemeinen. Es kann Ihnen wirklich helfen, die Funktionsweise Ihres Codes zu erkennen und auf mögliche Fehler hinzuweisen.
Bearbeiten
Wie Sphinxxx sagte, haben wir immer noch einen Fehler in unserer Logik. Sobald wir die Taste drücken
ELSE
und@Palindrome
auf 0 setzen , macht es keinen Sinn, fortzufahren. In der Tat konnten wir zu diesem Zeitpunkt nurRETURN
.Angesichts der Tatsache, dass wir jetzt nur
@Palindrome
für "Es ist immer noch möglich, dass dies ein Palindrom ist" verwenden, macht es keinen Sinn, es zu haben. Wir können die Variable loswerden und unsere Logik nur dann auf Kurzschluss bei Ausfall (derRETURN 0
) undRETURN 1
(einer positiven Reaktion) umschalten, wenn sie den gesamten Weg durch die Schleife zurücklegt. Sie werden feststellen, dass dies unsere Logik tatsächlich etwas vereinfacht.quelle
Sie können auch einen Nummerntabellenansatz verwenden.
Wenn Sie noch keine Hilfsnummerntabelle haben, können Sie eine wie folgt erstellen. Diese ist mit einer Million Zeilen gefüllt und eignet sich daher für Zeichenfolgen mit einer Länge von bis zu 2 Millionen Zeichen.
Das folgende vergleicht jedes Zeichen auf der linken Seite mit dem entsprechenden Partner auf der rechten Seite. Wenn Unstimmigkeiten festgestellt werden, kann dies zu einem Kurzschluss und der Rückgabe von 0 führen. Wenn die Zeichenfolge eine ungerade Länge hat, wird das mittlere Zeichen nicht überprüft, da dies das Ergebnis nicht verändert .
Wenn Sie sich nicht sicher sind, wie es funktioniert, sehen Sie es unten
Dies ist im Grunde derselbe Algorithmus wie in der Frage beschrieben, wird jedoch auf Mengenbasis und nicht als iterativer Verfahrenscode ausgeführt.
quelle
Die
REVERSE()
Methode "verbessert", dh nur die Hälfte des Strings umkehren:Ich erwarte nicht, dass etwas Seltsames passiert, wenn die Zeichenfolge eine ungerade Anzahl von Zeichen enthält. Das mittlere Zeichen muss nicht angekreuzt werden.
@Hvd bemerkte, dass dies möglicherweise nicht in allen Kollatierungen mit Ersatzpaaren richtig umgehen kann.
@srutzky kommentierte, dass es Zusatzzeichen / Ersatzpaare auf die gleiche Weise wie die
REVERSE()
Methode behandelt, da sie nur dann ordnungsgemäß funktionieren, wenn die Standardkollatierung der aktuellen Datenbank auf endet_SC
.quelle
Ohne zu benutzen
REVERSE
, was mir sofort einfällt, aber immer noch eine Funktion zu benutzen 1 ; Ich würde so etwas wie folgendes konstruieren.Dieser Teil hat einfach die vorhandene Funktion entfernt, falls sie bereits vorhanden ist:
Dies ist die Funktion selbst:
Hier testen wir die Funktion:
Dies vergleicht die erste Worthälfte mit der Umkehrung der letzten Worthälfte (ohne Verwendung der
REVERSE
Funktion). Dieser Code behandelt sowohl ungerade als auch gerade Wörter. Anstatt das ganze Wort zu durchlaufen, erhalten wir einfachLEFT
die erste Hälfte des Wortes und dann die letzte Hälfte des Wortes, um den umgekehrten Teil der rechten Hälfte zu erhalten. Wenn das Wort eine ungerade Länge hat, überspringen wir den mittleren Buchstaben, da er per Definition für beide "Hälften" gleich ist.1 - Funktionen können sehr langsam sein!
quelle
Ohne Verwendung von REVERSE ... Es macht immer Spaß, eine rekursive Lösung zu verwenden;) (Ich habe meine in SQL Server 2012, frühere Versionen haben möglicherweise Einschränkungen bei der Rekursion)
quelle
Dies ist eine Inline-TVF-freundliche Version von Martin Smiths Set-basierter Lösung , die zusätzlich mit ein paar überflüssigen Verbesserungen ausgestattet ist:
quelle
Aus Spaß gibt es hier eine benutzerdefinierte SQL Server 2016-Skalarfunktion mit der In-Memory-OLTP-Funktion:
quelle
Ein Hauptproblem, auf das Sie stoßen werden, besteht darin, dass ein Wert größer als 1
LEFT
oderRIGHT
mehrere Zeichen zurückgibt, nicht das Zeichen an dieser Position. Wenn Sie diese Testmethode beibehalten möchten, ist dies eine sehr einfache Möglichkeit, sie zu ändernDies wird immer das am weitesten rechts stehende Zeichen der linken Zeichenfolge und das am weitesten links stehende Zeichen der rechten Zeichenfolge erfassen.
Vielleicht wäre ein weniger umständlicher Weg, dies zu überprüfen, die Verwendung von
SUBSTRING
:Beachten Sie, dass
SUBSTRING
1-indiziert ist, daher der+ 1
in((LEN(String) - @n) + 1)
.quelle