Welche allgemeinen Tipps haben Sie zum Golfen in T-SQL? Ich bin auf der Suche nach Ideen, die auf Code-Golf-Probleme im Allgemeinen angewendet werden können, die zumindest etwas spezifisch für T-SQL sind. Bitte posten Sie einen Tipp pro Antwort.
Vielen Dank an Marcog für die originelle Idee. :)
Antworten:
Meine allgemeine Trickkiste:
@
ist eine gültige Variable in t-sql.iif
eine VB-Style-Case-Anweisung hinzugefügt . Dies ist fast immer kürzer als ein Äquivalentif
else
.\
Dies ist eine nützliche Methode, um eine Zahl als 0 in einem Geldtyp zu initialisieren. Sie können einen Wert durch Hinzufügen in einen Gleitkommawert umwandelne
. zB4e
oder\k
was setzt k auf den Wert 0,00 Geld.rCTE
scheinen die beste Möglichkeit zu sein, eine Nummerntabelle mit weniger als 100 Einträgen zu erstellen. Noch kürzer als mit spt_values. Wenn Sie mehr als 100 benötigen, fügen Sie diese über Kreuz hinzu.+=
und andere zusammengesetzte Operatoren wurden 2008 hinzugefügt. Verwenden Sie diese, um einige Zeichen zu sparen.;
.Select*from A,B where condition
ist kürzer alsselect*from A join b on condition
goto
Schleife um.STR()
ist die kürzeste Funktion, um ein Int in einen String zu verwandeln. Wenn Sie mehr als eine Konvertierung durchführen oder mehrere verschiedene Datentypen zusammenfassen müssen, ziehen Sie dieconcat
Funktion in Betracht . ZB'hello'+str(@)
ist kürzer alsconcat('hello',@)
, aberhello+str(@)+str(@a)
länger alsconcat('hello',@,@a)
Zum Beispiel sind diese beiden semantisch äquivalent.
Mit können Sie
Values
eine Tabelle oder Unterabfrage erstellen. Dies ist nur dann von Vorteil, wenn Sie einige konstante Zeilen benötigen.quelle
Codekomprimierung mit SQL
SQL ist wortreich, erzielt hohe Punktzahlen und kostet, so sehr wir es lieben,
SELECT FROM WHERE
bei jeder Verwendung 23 Byte. Sie können diese und andere wiederholte Wörter oder ganze Codeausschnitte komprimieren. Auf diese Weise verringern sich die Grenzkosten für wiederholten Code auf 1 Byte! *Wie das funktioniert:
Das Problem:
Die Vorabkosten liegen bei nahezu 100 Byte, und jede Zeile in der Ersetzungstabelle kostet weitere 6 Byte. Diese Art von Logik ist nur dann sehr effektiv, wenn Sie mit viel Code arbeiten, den Sie nicht kürzen können, oder wenn die Herausforderung auf Komprimierung basiert.
Hier ist ein Beispiel
Die Herausforderung besteht darin, die letzten 10 Vielfachen von 2,3 und 5 zu erhalten, die zu n führen. Nehmen wir an, dies ( 343 Byte Golf ) ist die beste Lösung, die ich finden konnte:
Beispiel nachdem der Code komprimiert wurde
Dies führt den gleichen Code wie oben aus, ist mit ~ 302 Bytes belegt .
quelle
SELECT @=REPLACE(@,i,j)FROM(VALUES(...)x(i,j)
anstatt eine einzelne Spalte mitLEFT()
und zu verwendenSUBSTRING()
. Wenn Sie 8 oder mehr haben, ist es ein guter Kompromiss, die zusätzlichen Anführungszeichen und Kommas zu vermeiden.SET @=REPLACE(REPLACE(REPLACE(...
Hier ist ein lustiger. Dadurch werden die Werte in einer Spalte in ein einzelnes Tupel konvertiert.
EDIT: Danke für die Kommentare. Der kürzeste Weg zum Aufrollen ohne XML-Tags ist:
Hinweis: Wenn XML eine gültige Ausgabe ist, können Sie die äußere Auswahl und das Paren weglassen. Auch das
column1+''
funktioniert nur für Streicher. Für Nummerntypen ist es am besten, dies zu tuncolumn1+0
quelle
<column_name>value1</column_name><column_name>value2</column_name>...
. Um eine CSV aus einer Spalte zu erhalten, können SieDECLARE @ VARCHAR(MAX)='';SELECT @+=column_name+',' FROM table_name;SELECT @
(danke für den ersten Tipp von @ MichaelB) diese zurückgebenvalue1,value2,...
. Es ist jedoch tatsächlich 9 Zeichen länger als Ihr XML-Trick :(Ltrim
ist nicht notwendig, da select (select ... for xml path ('')) ein zurückgibtnvarchar(max)
. Verwenden Sie zum Lösen der Spaltensache einfach einen nicht mutierenden Ausdruck. Für Zahlen können Sie tunv+0
, für Zeichenfolgen fügen Sie leere Zeichenfolgen usw. hinzu. Obwohl ich dies nicht wirklich als Golftipp betrachte, ist dies leider eine Realität, wie Abfragen in SQL Server geschrieben werden.In T-SQL können einige bitweise Operatoren verwendet werden .
Ich habe kein konkretes Beispiel, aber ich glaube, es ist eine gut zu wissende Tatsache, wenn man mit T-SQL Golf spielt.
quelle
x=0 or y=0
schreiben, können Sie diese als logisches Äquivalent schreiben, dasx|y=0
einige Bytes einspart!Drucken statt Auswählen
So einfach ist das! Also hier ist ein T-SQL / Python-Polyglot:
Probieren Sie es online aus
quelle
Wissenschaftliche Notation ist eine kürzere Methode, um sehr große und sehr kleine Zahlen auszudrücken, zB
select 1000000000
=select 1E9
undselect 0.000001
=select 1E-6
.quelle
Michael B erwähnte die Verwendung eines rekursiven CTE für eine Nummerntabelle , zeigte jedoch kein Beispiel. Hier ist eine MS-SQL-Version, die wir in diesem anderen Thread ausgearbeitet haben :
Beachten Sie, dass Sie den Startwert (
1 n
), das Intervall (n + 1
) und den Endwert (n < 99
) ändern können .Wenn Sie jedoch mehr als 100 Zeilen benötigen, müssen Sie Folgendes hinzufügen
option (maxrecursion 0)
:oder treten Sie dem rCTE bei:
Obwohl nicht garantiert ist, dass der letzte Befehl in numerischer Reihenfolge ohne ein zurückgegeben wird
ORDER BY 1
quelle
Verwenden Sie die GZIP-Komprimierung für sehr lange Zeichenfolgen!
Daher wusste ich, dass SQL 2016 eine
COMPRESS
Funktion (und eineDECOMPRESS
Funktion) hinzugefügt hat , die (endlich) die Möglichkeit bietet, einen String oder eine Binärdatei mit GZIP zu versehen.Das Problem ist, dass es nicht sofort klar ist, wie man dies zum Golfen nutzen kann.
COMPRESS
kann eine Zeichenfolge annehmen, gibt jedoch a zurückVARBINARY
, das in Bytes kürzer ist (wenn es in einem SQL-VARBINARY
Feld gespeichert ist), in Zeichen jedoch länger ist (unformatiertes Hex).Ich habe damit schon früher gespielt, konnte aber endlich eine funktionierende Version zusammenstellen, basierend auf dieser alten Antwort auf SO . Dieser Beitrag verwendet die neuen GZIP-Funktionen nicht, konvertiert jedoch eine
VARBINARY
in eine Base-64-codierte Zeichenfolge. Wir mussten nur die neuen Funktionen an der richtigen Stelle einfügen und ein bisschen Golf spielen.Hier ist der Code, mit dem Sie Ihre sehr lange Zeichenfolge in die Base-64-codierte komprimierte Zeichenfolge konvertieren können:
Nehmen Sie die Ausgabe und verwenden Sie sie in Ihrem Code anstelle der ursprünglichen langen Zeichenfolge, zusammen mit:
Also anstelle Ihres ursprünglichen Codes ( 1471 Bytes )
Sie würden dies haben ( 1034 Bytes ):
Siehe diese Antwort, die mir fast 200 Bytes erspart hat.
Ich habe nicht nachgerechnet, aber aufgrund des Overheads wird dies nur für extrem lange Saiten effektiv sein. Es gibt wahrscheinlich andere Orte, an denen dies nicht möglich ist. Ich habe bereits herausgefunden, dass du
SELECT
es musst, du kannst es nichtPRINT
, sonst bekommst du:EDIT : Kürzere Version des Dekomprimierungscodes mit freundlicher Genehmigung von @digscoop :
Sparen Sie 10 Bytes, indem Sie die äußere
CAST
in eine implizite Konvertierung ändernCONCAT
:Sie können
XML
anstelle von auch eine Variable vom Typ deklarierenVARCHAR(MAX)
und im Inneren speichernCAST
:Dies ist an sich etwas länger, aber wenn Sie es aus anderen Gründen in einer Variablen benötigen, kann es hilfreich sein.
quelle
Ein paar Gedanken zum Erstellen und Verwenden von Tabellen für Herausforderungen:
1. Die SQL-Eingabe kann über eine bereits vorhandene Tabelle erfolgen
Code Golf Eingabe / Ausgabemethoden :
Das Erstellen und Auffüllen dieser Tabelle mit Eingabewerten zählt nicht für Ihre Bytesumme. Sie können lediglich davon ausgehen, dass sie bereits vorhanden ist.
Dies bedeutet, dass Ihre Berechnungen über einfaches SELECT aus der Eingabetabelle ausgegeben werden können:
2. Erstellen Sie nach Möglichkeit überhaupt keine Tabelle
Anstelle von (69 Bytes):
Mach einfach (43 Bytes):
3. Erstellen Sie nach Möglichkeit die Tabelle mit einem SELECT INTO
Anstelle von (39 Bytes):
Tun Sie dies (17 Bytes):
4: Überlegen Sie, ob Sie mehrere Spalten zusammenfügen möchten
Hier sind zwei Varianten, die dieselbe Ausgabe zurückgeben:
Nach einigen Tests ist die obere Version (mehrere Spalten) mit 7 oder weniger Zeilen kürzer , die untere Version (aufgrund von LEFT und SUBSTRING) mit 8 oder mehr Zeilen kürzer . Ihr Kilometerstand kann je nach Ihren genauen Daten variieren.
5: Verwenden Sie REPLACE und EXEC für sehr lange Textsequenzen
In der Ader der ausgezeichneten Antwort des comfortablydrei , wenn Sie 15 oder mehr Werte , die Verwendung
REPLACE
auf einem Symbol loszuwerden, die wiederholt zu bekommen'),('
Separatoren zwischen den Elementen:114 Zeichen:
112 Zeichen:
Wenn Sie aus anderen Gründen bereits dynamisches SQL verwenden (oder mehrere Ersetzungen haben), ist der Schwellenwert, bei dem dies sinnvoll ist, viel niedriger.
6: Verwenden Sie ein SELECT mit benannten Spalten anstelle einer Reihe von Variablen
Inspiriert von der hervorragenden Antwort von jmlt hier , verwenden Sie Strings über ein SELECT erneut:
kehrt zurück
(Für MS SQL habe ich das
\t
in ein Inline-Return geändertCONCAT()
und+
in um Bytes zu sparen).quelle
Kennzeichnen Sie Ihren Code für die Hervorhebung der T-SQL-Syntax
Anstatt nur:
Fügen Sie ein Sprach-Tag wie das folgende hinzu:
und das Ergebnis wird sein:
quelle
Nutzen Sie die neuen Funktionen in MS SQL 2016 und SQL 2017
Wenn Sie keine lokalen Kopien zum Arbeiten haben, können Sie mit dem StackExchange Data Explorer (SQL 2016) oder mit dbfiddle.uk (SQL 2016 oder SQL "vNext") online spielen .
STRING_SPLIT ( SQL 2016 und höher )
Wenn Sie die Tabelle aliasen oder auf den Spaltennamen verweisen müssen:
TRIM ( SQL 2017 oder höher )
Kürzer als
RTRIM()
und sicherlich kürzer alsLTRIM(RTRIM())
.Es besteht auch die Möglichkeit, andere Zeichen oder Zeichensätze entweder vom Anfang oder vom Ende zu entfernen :
kehrt zurück
L Server 2
TRANSLATE ( SQL 2017 oder höher )
TRANSLATE
Ermöglicht das Ersetzen mehrerer Zeichen in einem Schritt anstelle mehrerer verschachtelterREPLACE
Anweisungen. Feiern Sie aber nicht zu viel, es werden nur einzelne Zeichen durch unterschiedliche Einzelzeichen ersetzt.Jedes Zeichen in der zweiten Zeichenfolge wird durch das entsprechende Zeichen in der dritten Zeichenfolge ersetzt.
Sieht so aus, als könnten wir eine Menge Charaktere mit so etwas wie eliminieren
REPLACE(TRANSLATE('source string','ABCD','XXXX'),'X','')
Einige weitere interessante, wie
CONCAT_WS
undSTRING_AGG
die sind wahrscheinlich auch einen Blick wert.quelle
Heilige Kuh, ich habe das Wunder von
PARSENAME
( SQL 2012 oder höher ) entdeckt.Die Funktion wurde erstellt, um die Teile eines Objektnamens zu isolieren
servername.dbname.dbo.tablename
, funktioniert jedoch für alle durch Punkte getrennten Werte. Denken Sie daran, es zählt von rechts , nicht von links:Wenn Sie weniger als 4 durch Punkte getrennte Werte haben, wird dieser
NULL
für den Rest zurückgegeben (zählt jedoch weiterhin von rechts nach links ):Hier kommt die Magie ins Spiel: Kombinieren Sie sie mit
STRING_SPLIT
(2016 oder höher), um In-Memory-Mehrspaltentabellen zu erstellen !!Alt und kaputt:
Neue Schärfe:
Ihre tatsächlichen Einsparungen hängen natürlich von der Größe und dem Inhalt der Tabelle ab und davon, wie genau Sie sie verwenden.
Beachten Sie, dass Sie bei Feldern mit konstanter Breite wahrscheinlich besser die Option
LEFT
und verwendenRIGHT
, um sie zu trennenPARSENAME
(nicht nur, weil die Funktionsnamen kürzer sind, sondern auch, weil Sie die Trennzeichen vollständig entfernen können).quelle
Noch ein paar verwandte Tricks, die ich gesehen und bewahren wollte:
GO #
diese Taste, um einen Block eine bestimmte Anzahl von Malen zu wiederholen .Ich habe diesen cleveren Trick bei Pauls exzellenter Antwort gesehen .
Dies würde natürlich alle Zählervariablen im Block zurücksetzen, so dass Sie dies gegen eine
WHILE
Schleife oder einex: ... GOTO x
Schleife abwägen müssten .SELECT TOP ... FROM systypes
Aus der gleichen Frage wie Paulus oben verwendete Anuj Tripathi den folgenden Trick :
oder, wie von pinkfloydx33 in den Kommentaren vorgeschlagen:
Hinweis : Dies beruht nicht auf einen der tatsächlichen Inhalte von
systypes
, nur , dass die Systemansicht existiert (was es tut in jeder MS SQL - Datenbank) und enthält mindestens 10 Zeilen (es sieht aus 34 enthält, für die neuesten Versionen von SQL ). Ich konnte keine Systemansichten mit kürzeren Namen finden (für die keinsys.
Präfix erforderlich war ), daher ist dies möglicherweise ideal.quelle
In dieser Frage auf dba.stackexchange finden Sie einige interessante Ideen zum Hinzufügen einer Zahlenspalte zu einem STRING_SPLIT-Ergebnis.
Bei einer Zeichenfolge wie
'one,two,three,four,five'
möchten wir Folgendes erhalten:Per Joe Obbishs Antwort, Verwendung
ROW_NUMBER()
und Reihenfolge nachNULL
oder einer Konstanten:Verwenden Sie für
SEQUENCE
die Antwort von Paul White Folgendes :Sequenzen sind interessante persistente Objekte; Sie können den Datentyp, den Min- und Max-Wert, das Intervall und den Zeilenumbruch definieren:
Per Biju Joses Antwort können Sie die
IDENTITY()
Funktion (die nicht mit derIDENTITY
Eigenschaft in Verbindung mit einem INSERT identisch ist) verwenden :Beachten Sie, dass die letzten beiden Parameter in
IDENTITY(INT,1,1)
optional sind und standardmäßig 1 sind, wenn sie ausgeschlossen werden.quelle
ORDER BY
wenn ich damit durchkomme (siehe meine Antwort auf Toasty, Burnt, Brulee zum Beispiel).Soeben wurde festgestellt, dass Sie Ziffern für ein einzelnes Zeichen verwenden können
REPLACE
, um Anführungszeichen zu entfernen :Dies liegt daran,
REPLACE
dass eine implizite Konvertierung in einen String erfolgt.Beide erzeugen die gleiche Ausgabe:
quelle
_ und # sind gültige Aliase. Ich benutze sie mit CROSS APPLY, um es so erscheinen zu lassen, dass die Spalten, die es zurückgibt, Teil der FROM-Klausel sind, z
Das gefällt mir, wenn der einzige Zweck von CROSS APPLY darin besteht, einen Ausdruck zu berechnen.
Übrigens ist die Verwendung von APPLY zur Berechnung von Unterausdrücken eine gute Möglichkeit, Ihren Code trockener (und kürzer) zu machen. Nach dem, was ich in den Ausführungsplänen gesehen habe, entstehen diesem Ansatz keine zusätzlichen Kosten. Der Compiler stellt fest, dass Sie nur etwas berechnen, und behandelt es wie jeden anderen Ausdruck.
quelle