Jakie masz ogólne wskazówki na temat gry w golfa w T-SQL? Szukam pomysłów, które można zastosować do ogólnych problemów z golfem, które są przynajmniej nieco specyficzne dla T-SQL. Proszę zamieścić jedną wskazówkę na odpowiedź.
Dzięki Marcog za oryginalny pomysł. :)
Odpowiedzi:
Moja ogólna torba sztuczek:
@
jest poprawną zmienną w t-sql.iif
instrukcję przypadku w stylu VB. Jest to prawie zawsze krótsze niż odpowiednikif
else
.\
to przydatny sposób na zainicjowanie liczby jako 0 w typie pieniężnym. Możesz przekonwertować wartość na zmiennoprzecinkową, dodające
. np.4e
lub\k
która ustawi k na wartość 0,00 pieniędzy.rCTE
wydaje się być najlepszym sposobem na utworzenie tabeli liczb zawierającej mniej niż 100 wpisów. Nawet krótszy niż przy użyciu spt_values. Jeśli potrzebujesz więcej niż 100, połącz krzyżowo i dodaj je.+=
i inne operatory złożone zostały dodane w 2008 roku. Użyj ich, aby zaoszczędzić kilka znaków.;
.Select*from A,B where condition
jest krótszy niżselect*from A join b on condition
goto
pętlę stylu do- while.STR()
to najkrótsza funkcja służąca do zamiany int na ciąg. Jeśli wykonujesz więcej niż jedną konwersję lub konieczne może być połączenie wielu różnych typów danych, rozważ tęconcat
funkcję. Np.'hello'+str(@)
Jest krótszy niżconcat('hello',@)
, alehello+str(@)+str(@a)
dłuższy niżconcat('hello',@,@a)
Na przykład te dwa są semantycznie równoważne.
Możesz użyć
Values
do utworzenia tabeli lub podzapytania. Będzie to naprawdę korzystne, jeśli potrzebujesz kilku stałych rzędów.źródło
Kompresja kodu za pomocą SQL
SQL jest trudny, osiąga wysokie wyniki i tak bardzo, jak go kochamy,
SELECT FROM WHERE
kosztuje 23 bajty przy każdym użyciu. Możesz skompresować te i inne powtarzające się słowa lub całe fragmenty kodu. Spowoduje to zmniejszenie kosztu krańcowego powtarzanego kodu do 1 bajtu! *Jak to działa:
Problem:
Koszt początkowy wynosi prawie 100 bajtów, a każdy wiersz w tabeli wymiany kosztuje kolejne 6 bajtów. Tego rodzaju logika nie będzie bardzo skuteczna, chyba że pracujesz z dużą ilością kodu, którego nie można zmniejszyć lub wyzwanie jest oparte na kompresji.
Oto przykład
Wyzwanie polega na uzyskaniu ostatnich 10 wielokrotności 2,3 i 5 prowadzących do n. Powiedzmy, że to ( 343 bajty w golfa ) jest najlepszym rozwiązaniem, jakie mogłem wymyślić:
Przykład po skompresowaniu kodu
Wykonuje to ten sam kod, co powyżej, ma ~ 302 bajtów .
źródło
SELECT @=REPLACE(@,i,j)FROM(VALUES(...)x(i,j)
zamiast używać pojedynczej kolumny zLEFT()
iSUBSTRING()
. Jeśli masz 8 lub więcej, unikanie dodatkowych cytatów i przecinków jest dobrym kompromisem.SET @=REPLACE(REPLACE(REPLACE(...
Oto zabawny. Spowoduje to przekształcenie wartości w kolumnie w jedną krotkę.
EDYCJA: Dziękuję za komentarze. Wygląda na to, że najkrótszym sposobem zwijania bez tagów XML jest:
Uwaga: jeśli XML jest prawidłowym wyjściem, możesz pominąć zewnętrzny wybór i parens. Również
column1+''
, działa tylko dla ciągów. W przypadku typów liczb najlepiej to zrobićcolumn1+0
źródło
<column_name>value1</column_name><column_name>value2</column_name>...
. Aby mieć plik CSV z kolumny, możeszDECLARE @ VARCHAR(MAX)='';SELECT @+=column_name+',' FROM table_name;SELECT @
(dzięki za pierwszą wskazówkę @ MichaelB), który wrócivalue1,value2,...
. Jednak w rzeczywistości jest on o 9 znaków dłuższy niż sztuczka XML :(Ltrim
nie jest konieczne, ponieważ select (select ... for xml path ('')) zwraca annvarchar(max)
. Ponadto, aby rozwiązać problem z kolumną, po prostu użyj niemutującego wyrażenia. W przypadku liczb można zrobićv+0
, w przypadku łańcucha dodać pusty ciąg itp. Chociaż tak naprawdę nie uważam tego za wskazówkę golfową, jest to niestety rzeczywistość pisania zapytań na serwerze SQL.Możliwe jest użycie niektórych operatorów bitowych w T-SQL .
Nie mam konkretnego przykładu, ale uważam, że dobrze jest wiedzieć, kiedy gra się w golfa w T-SQL.
źródło
x=0 or y=0
, możesz napisać go jako logiczny odpowiednik,x|y=0
który pozwala zaoszczędzić sporo bajtów!Drukuj zamiast Wybierz
To takie proste! Oto poliglota T-SQL / Python:
Wypróbuj online
źródło
Notacja naukowa jest krótszą metodą wyrażania bardzo dużych i bardzo małych liczb, np.
select 1000000000
=select 1E9
Iselect 0.000001
=select 1E-6
.źródło
Michael B wspomniał o użyciu rekurencyjnego CTE dla tabeli liczb , ale nie pokazał przykładu. Oto wersja MS-SQL, którą opracowaliśmy w tym innym wątku :
Pamiętaj, że możesz zmienić wartość początkową (
1 n
), interwał (n + 1
) i wartość końcową (n < 99
).Jeśli potrzebujesz więcej niż 100 wierszy, musisz dodać
option (maxrecursion 0)
:lub dołącz do rCTE do siebie:
Chociaż ten ostatni nie gwarantuje zwrotu w kolejności numerycznej bez znaku
ORDER BY 1
źródło
Użyj kompresji GZIP dla bardzo długich łańcuchów!
Wiedziałem więc, że SQL 2016 dodał
COMPRESS
funkcję (iDECOMPRESS
funkcję), która (w końcu) daje możliwość GZIP-a łańcucha lub pliku binarnego.Problem polega na tym, że nie jest od razu jasne, jak wykorzystać to do gry w golfa;
COMPRESS
może pobrać ciąg, ale zwraca aVARBINARY
, który jest krótszy w bajtach (gdy jest przechowywany wVARBINARY
polu SQL ), ale jest dłuższy w znakach (nieprzetworzony hex).Grałem z tym wcześniej, ale w końcu udało mi się stworzyć działającą wersję, opartą na starej odpowiedzi na SO . Ten post nie korzysta z nowych funkcji GZIP, ale konwertuje
VARBINARY
ciąg znaków na kodowany w Base-64. Musieliśmy tylko wstawić nowe funkcje we właściwe miejsce i nieco poprawić grę.Oto kod, którego można użyć do konwersji bardzo długiego ciągu na skompresowany ciąg zakodowany w standardzie Base-64:
Weź wynik i użyj go w kodzie zamiast oryginalnego długiego łańcucha wraz z:
Zamiast oryginalnego kodu ( 1471 bajtów )
miałbyś to ( 1034 bajty ):
Zobacz tę odpowiedź, która pozwoliła mi zaoszczędzić prawie 200 bajtów.
Nie zrobiłem matematyki, ale najwyraźniej z powodu narzutów będzie to skuteczne tylko w przypadku bardzo długich strun. Są prawdopodobnie inne miejsca, z których nie można korzystać; Już odkryłem, że musisz to
SELECT
zrobić, nie możesz tegoPRINT
zrobić, w przeciwnym razie otrzymasz:EDYCJA : Krótsza wersja kodu dekompresyjnego, dzięki uprzejmości @digscoop :
Zaoszczędź 10 bajtów, zmieniając
CAST
konwersję zewnętrzną na niejawną za pomocąCONCAT
:Możesz także zadeklarować zmienną typu
XML
zamiastVARCHAR(MAX)
i zapisać na wewnętrznejCAST
:Jest to nieco dłużej samo w sobie, ale jeśli potrzebujesz go w zmiennej z innych powodów, może to pomóc.
źródło
Kilka przemyśleń na temat tworzenia i używania tabel do wyzwań:
1. Dane wejściowe SQL można pobrać z istniejącej tabeli
Metody wejścia / wyjścia Code Golf :
Utworzenie i wypełnienie tej tabeli wartościami wejściowymi nie wlicza się do całkowitej liczby bajtów, możesz po prostu założyć, że już tam jest.
Oznacza to, że twoje obliczenia mogą być generowane przez prosty WYBÓR z tabeli wprowadzania:
2. Jeśli to możliwe, w ogóle nie twórz tabeli
Zamiast (69 bajtów):
Po prostu zrób (43 bajty):
3. Jeśli to możliwe, utwórz tabelę przy pomocy WYBIERZ DO
Zamiast (39 bajtów):
Zrób to (17 bajtów):
4: Rozważ połączenie wielu kolumn razem
Oto dwie odmiany, które zwracają ten sam wynik:
Po niektórych testach górna wersja (wiele kolumn) wydaje się krótsza z 7 lub mniejszą liczbą wierszy , dolna wersja (z powodu LEWEJ i SUBSTRINGU) jest krótsza z 8 lub więcej wierszami . Twój przebieg może się różnić w zależności od dokładnych danych.
5: Użyj REPLACE i EXEC dla bardzo długich sekwencji tekstu
Zgodnie z doskonałą odpowiedzią komfortowo drei , jeśli masz 15 lub więcej wartości , użyj
REPLACE
symbolu, aby pozbyć się powtarzających się'),('
separatorów między elementami:114 znaków:
112 znaków:
Jeśli używasz już dynamicznego SQL z innych powodów (lub masz wiele zamienników), to próg, w którym warto, jest znacznie niższy.
6: Użyj SELECT z nazwanymi kolumnami zamiast szeregu zmiennych
Zainspirowany doskonałą odpowiedzią jmlt tutaj , ponownie użyj ciągów znaków poprzez SELECT:
zwroty
(W przypadku MS SQL zmieniłem
\t
zwrot na wbudowany i zmieniłemCONCAT()
na+
na zapisywanie bajtów).źródło
Oznacz swój kod do podświetlania składni T-SQL
Zamiast po prostu:
Dołącz tag języka taki jak ten:
a wynikiem będzie:
źródło
Skorzystaj z nowych funkcji / funkcji w MS SQL 2016 i SQL 2017
Jeśli nie masz kopii lokalnych do pracy, możesz grać online za pomocą StackExchange Data Explorer (SQL 2016) lub dbfiddle.uk (SQL 2016 lub SQL „vNext”).
STRING_SPLIT ( SQL 2016 i nowsze wersje )
Jeśli chcesz dokonać aliasu tabeli lub odwołać się do nazwy kolumny:
TRIM ( SQL 2017 lub nowszy )
Krótszy niż
RTRIM()
i na pewno krótszy niżLTRIM(RTRIM())
.Ma również opcję usuwania innych znaków lub zestawów znaków na początku lub na końcu:
zwroty
L Server 2
TŁUMACZ ( SQL 2017 lub nowszy )
TRANSLATE
pozwala zastąpić wiele znaków w jednym kroku, a nie kilka zagnieżdżonychREPLACE
instrukcji. Ale nie świętuj zbyt wiele, to zastępuje pojedyncze pojedyncze znaki różnymi pojedynczymi znakami.Każdy znak w drugim ciągu jest zastępowany przez odpowiedni znak w 3 ciągu.
Wygląda na to, że moglibyśmy wyeliminować kilka postaci za pomocą czegoś takiego
REPLACE(TRANSLATE('source string','ABCD','XXXX'),'X','')
Również niektóre bardziej interesujące, takie jak te
CONCAT_WS
iSTRING_AGG
które prawdopodobnie są warte obejrzenia.źródło
Święta krowa, odkryłem cud
PARSENAME
( SQL 2012 lub wyższy ).Funkcja została zbudowana w celu wyodrębnienia części nazwy obiektu jak
servername.dbname.dbo.tablename
, ale działa z dowolnymi wartościami oddzielonymi kropkami. Pamiętaj tylko, że liczy się od prawej , a nie lewej:Jeśli masz mniej niż 4 wartości oddzielone kropkami, wróci
NULL
do reszty (ale nadal liczy się od prawej do lewej ):Tutaj jednak pojawia się magia: połącz ją z
STRING_SPLIT
(2016 lub nowszą wersją), aby stworzyć tabele wielokolumnowe w pamięci !!Stare i zniszczone:
Nowa gorliwość:
Oczywiście twoje rzeczywiste oszczędności zależą od wielkości i zawartości tabeli oraz tego, jak dokładnie z niej korzystasz.
Zauważ, że jeśli twoje pola mają stałą szerokość, prawdopodobnie lepiej jest użyć
LEFT
iRIGHT
oddzielić je zamiastPARSENAME
(nie tylko dlatego, że nazwy funkcji są krótsze, ale także dlatego, że możesz całkowicie wyeliminować separatory).źródło
Kilka innych niezwiązanych ze sobą sztuczek, które widziałem i chciałem zachować:
GO #
aby powtórzyć blok określoną liczbę razy .Widziałem tę sprytną sztuczkę na doskonałej odpowiedzi Paula .
Spowodowałoby to oczywiście zresetowanie wszystkich zmiennych przeciwnych w bloku, więc należałoby to porównać z
WHILE
pętlą lubx: ... GOTO x
pętlą.SELECT TOP ... FROM systypes
Z tego samego pytania, co powyższe pytanie Paula, Anuj Tripathi zastosował następującą sztuczkę :
lub, jak sugeruje pinkfloydx33 w komentarzach:
Uwaga ta nie opiera się na żadnym z aktualnych treści o
systypes
, właśnie, że widok system istnieje (co robi w każdej bazie danych MS SQL) i zawiera co najmniej 10 wierszy (wygląda zawierać 34, dla najnowszych wersji SQL ). Nie mogłem znaleźć widoków systemu o krótszych nazwach (które nie wymagałybysys.
prefiksu), więc może to być idealne.źródło
Zobacz to pytanie na dba.stackexchange aby uzyskać kilka interesujących pomysłów na dodanie kolumny liczb do wyniku STRING_SPLIT.
Biorąc pod uwagę ciąg
'one,two,three,four,five'
, chcemy uzyskać coś takiego:Odpowiedź, odpowiedź
ROW_NUMBER()
i zamówienie według Joe ObbishaNULL
lub stała:Według odpowiedzi Paula White'a użyj
SEQUENCE
:Sekwencje są interesującymi trwałymi obiektami; możesz zdefiniować typ danych, wartość minimalną i maksymalną, interwał oraz to, czy będzie się on owijał do początku:
Za odpowiedź Biju Jose, można korzystać z
IDENTITY()
funkcji (co jest nie tak samo jak naIDENTITY
nieruchomości w połączeniu z wkładką:Pamiętaj, że dwa ostatnie parametry
IDENTITY(INT,1,1)
są opcjonalne i domyślnie wynoszą 1, jeśli zostaną wykluczone.źródło
ORDER BY
czy uda mi się uciec (patrz na przykład moja odpowiedź na Toasty, Burnt, Brulee ).Właśnie odkryłem, że możesz użyć cyfr dla pojedynczego znaku,
REPLACE
aby wyeliminować cudzysłowy :To dlatego, że
REPLACE
z niejawnej konwersji na ciąg znaków.Oba wytwarzają tę samą moc wyjściową:
źródło
_ i # są poprawnymi aliasami. Używam ich z APLIKACJĄ KRZYŻOWĄ, aby wyglądało, że zwracane kolumny są częścią klauzuli FROM, np
Podoba mi się, gdy jedynym celem aplikacji CROSS APPLY jest obliczenie wyrażenia.
W tym przypadku użycie APPLY do obliczania podwyrażeń to fajny sposób na sprawienie, by Twój kod był OSUSZONY (i krótszy). Z tego, co widziałem w planach wykonania, takie podejście nie wiąże się z dodatkowymi kosztami. Kompilator odkrywa, że po prostu coś obliczasz i traktuje to jak każde inne wyrażenie.
źródło