Какие общие советы у вас есть для игры в гольф в T-SQL? Я ищу идеи, которые могут быть применены к задачам по коду для гольфа в целом, которые хотя бы несколько специфичны для T-SQL. Пожалуйста, оставьте один совет за ответ.
Спасибо Marcog за оригинальную идею. :)
Ответы:
Моя общая сумка трюков ::
@
является допустимой переменной в t-sql.iif
утверждение в стиле VB. Это почти всегда короче, чем эквивалентif
else
.\
полезный способ инициализировать число как 0 в денежном типе. Вы можете преобразовать значение в число с плавающей точкой, добавивe
. например,4e
или\k
который установит k в значение 0,00 денег.rCTE
кажется, лучший способ создать таблицу чисел менее 100 записей. Даже короче, чем использование spt_values. Если вам нужно больше 100, перекрестное соединение и добавьте их.+=
и другие составные операторы были добавлены в 2008 году. Используйте их, чтобы сохранить несколько символов.;
.Select*from A,B where condition
короче чемselect*from A join b on condition
goto
цикл стиля do- while.STR()
является самой короткой функцией, чтобы превратить int в строку. Если вы выполняете более одного преобразования или вам может потребоваться объединить множество различных типов данных, рассмотритеconcat
функцию. Например'hello'+str(@)
, корочеconcat('hello',@)
, ноhello+str(@)+str(@a)
длиннее, чемconcat('hello',@,@a)
Например, эти два семантически эквивалентны.
Вы можете использовать
Values
для создания таблицы или подзапроса. Это будет действительно полезно, если вам нужно несколько постоянных строк.источник
Сжатие кода с использованием SQL
SQL многословен, имеет высокие оценки, и, сколько бы мы его ни любили,
SELECT FROM WHERE
стоит 23 байта при каждом использовании. Вы можете сжать эти и другие повторяющиеся слова или целые фрагменты кода. Это снизит предельную стоимость повторного кода до 1 байта! *Как это работает:
Проблема:
Предварительная стоимость составляет около 100 байтов, а каждая строка в таблице замены стоит еще 6 байтов. Такая логика не будет очень эффективной, если вы не работаете с большим количеством кода, который не можете урезать, или если задача основана на сжатии.
Вот пример
Задача состоит в том, чтобы получить последние 10 кратных 2,3 и 5, ведущих к n. Скажем, это ( 343 байта в гольфе ) - лучшее решение, которое я мог придумать:
Пример после сжатия кода
Это выполняет тот же код, что и выше, это ~ 302 байта в гольфе .
источник
SELECT @=REPLACE(@,i,j)FROM(VALUES(...)x(i,j)
вместо того чтобы использовать один столбец сLEFT()
иSUBSTRING()
. Если у вас есть 8 или более, то избегание лишних кавычек и запятых является хорошим компромиссом.SET @=REPLACE(REPLACE(REPLACE(...
Вот забавный Это преобразует значения в столбце в один кортеж.
РЕДАКТИРОВАТЬ: Спасибо за комментарии. Кажется, что самый короткий способ свернуть без тегов XML:
Примечание: если XML является допустимым выводом, вы можете опустить внешние select и parens. Кроме того
column1+''
, работает только для строк. Для чисел лучше всего делатьcolumn1+0
источник
<column_name>value1</column_name><column_name>value2</column_name>...
. Чтобы получить CSV из столбца, вы можетеDECLARE @ VARCHAR(MAX)='';SELECT @+=column_name+',' FROM table_name;SELECT @
(спасибо за первый совет @ MichaelB), который вернетсяvalue1,value2,...
. Однако на самом деле это на 9 символов длиннее вашего трюка с XML :(Ltrim
не требуется, так как select (select ... для пути xml ('')) возвращаетnvarchar(max)
. Кроме того, для решения этой проблемы просто используйте не мутирующее выражение. Для чисел, которые вы можете сделатьv+0
, для строки добавить пустую строку и т. Д. Хотя я не считаю это подсказкой для игры в гольф, это просто печальная реальность того, как писать запросы на сервере SQL.В T-SQL можно использовать несколько побитовых операторов .
У меня нет конкретного примера, но я считаю, что это полезный факт при игре в гольф на T-SQL.
источник
x=0 or y=0
, вы можете записать его как логически эквивалентный,x|y=0
который экономит немало байтов!Распечатать вместо выбора
Это так просто! Итак, вот полиглот T-SQL / Python:
Попробуйте онлайн
источник
Научная запись - это более короткий метод для выражения очень больших и очень маленьких чисел, например,
select 1000000000
=select 1E9
иselect 0.000001
=select 1E-6
.источник
Майкл Б упомянул об использовании рекурсивного CTE для таблицы чисел , но не показал пример. Вот версия MS-SQL, которую мы разработали в этом другом потоке :
Обратите внимание, что вы можете изменить начальное значение (
1 n
), интервал (n + 1
) и конечное значение (n < 99
).Если вам нужно более 100 строк, вам нужно добавить
option (maxrecursion 0)
:или присоединитесь к rCTE к себе:
Хотя этот последний не гарантированно будет возвращаться в числовом порядке без
ORDER BY 1
источник
Используйте сжатие GZIP для очень длинных строк!
Итак, я знал, что в SQL 2016 добавлена
COMPRESS
функция (иDECOMPRESS
функция), которая (наконец-то) предоставляет возможность GZIP-строки или двоичного файла.Проблема в том, что не сразу понятно, как воспользоваться этим для игры в гольф;
COMPRESS
может принимать строку, но возвращает aVARBINARY
, которое короче в байтах (при хранении вVARBINARY
поле SQL ), но длиннее в символах (необработанный шестнадцатеричный код).Я играл с этим раньше, но я наконец смог собрать рабочую версию, основанную на этом старом ответе на SO . Этот пост не использует новые функции GZIP, но он конвертирует в
VARBINARY
строку в кодировке Base-64. Нам просто нужно было вставить новые функции в нужное место и немного поиграть.Вот код, который вы можете использовать для преобразования вашей очень длинной строки в сжатую строку в кодировке Base-64:
Возьмите вывод и используйте его в своем коде вместо оригинальной длинной строки вместе с:
Так что вместо вашего исходного кода ( 1471 байт )
у тебя было бы это ( 1034 байта ):
Посмотрите этот ответ, который спас мне почти 200 байтов.
Я не занимался математикой, но, очевидно, из-за накладных расходов это будет эффективно только для очень длинных струн. Возможно, есть и другие места, которые нельзя использовать; Я уже обнаружил, что ты должен
SELECT
, ты не можешьPRINT
сделать, иначе вы получите:РЕДАКТИРОВАТЬ : более короткая версия кода распаковки, любезно предоставлено @digscoop :
Сохраните 10 байтов, изменив внешнее
CAST
на неявное преобразование, используяCONCAT
:Вы также можете объявить переменную типа
XML
вместоVARCHAR(MAX)
и сохранить на внутреннемCAST
:Это немного длиннее само по себе, но если вам нужно это в переменной по другим причинам, то это может помочь.
источник
Несколько мыслей о создании и использовании таблиц для испытаний:
1. Ввод SQL может быть выполнен через уже существующую таблицу
Code Golf Методы ввода / вывода :
Создание и заполнение этой таблицы входными значениями не учитывается в сумме байтов, вы можете просто предположить, что она уже есть.
Это означает, что ваши вычисления могут выводиться с помощью простого SELECT из входной таблицы:
2. Если возможно, вообще не создавайте таблицу
Вместо (69 байт):
Просто сделайте (43 байта):
3. Если возможно, создайте таблицу с помощью SELECT INTO
Вместо (39 байт):
Сделайте это (17 байт):
4: Рассмотрите возможность объединения нескольких столбцов
Вот два варианта, которые возвращают один и тот же результат:
После некоторого тестирования верхняя версия (несколько столбцов) кажется короче с 7 или менее строками , нижняя версия (из-за LEFT и SUBSTRING) короче с 8 или более строками . Ваш пробег может варьироваться в зависимости от ваших точных данных.
5: используйте REPLACE и EXEC для очень длинных последовательностей текста
В отличном ответе comforblydrei , если у вас есть 15 или более значений , используйте
REPLACE
символ, чтобы избавиться от повторяющихся'),('
разделителей между элементами:114 символов:
112 символов:
Если вы уже используете динамический SQL по другим причинам (или имеете несколько замен), то порог, в котором это стоит, гораздо ниже.
6: используйте SELECT с именованными столбцами вместо набора переменных
Вдохновленный отличным ответом jmlt здесь , повторно используйте строки через SELECT:
возвращается
(Для MS SQL я изменил
\t
к возвращению в линии, и переменилCONCAT()
на ,+
чтобы сохранить байты).источник
Пометьте свой код для подсветки синтаксиса T-SQL
Вместо просто:
Включите языковой тег, подобный этому:
и результат будет:
источник
Воспользуйтесь новыми функциями / функциями в MS SQL 2016 и SQL 2017
Если у вас нет локальных копий, с которыми можно работать, вы можете играть в онлайн с помощью Проводника данных StackExchange (SQL 2016) или dbfiddle.uk (SQL 2016 или SQL «vNext»).
STRING_SPLIT ( SQL 2016 и более поздние версии )
Если вам нужно создать псевдоним таблицы или обратиться к имени столбца:
TRIM ( SQL 2017 или более поздняя версия )
Короче чем
RTRIM()
и конечно короче чемLTRIM(RTRIM())
.Также есть возможность удалить другие символы или наборы символов из начала или конца:
возвращается
L Server 2
ПЕРЕВОД ( SQL 2017 или более поздняя версия )
TRANSLATE
позволяет заменить несколько символов за один шаг, а не кучу вложенныхREPLACE
операторов. Но не празднуйте слишком много, он заменяет только отдельных персонажей разными персонажами.Каждый символ во второй строке заменяется соответствующим символом в 3-й строке.
Похоже, мы могли бы устранить кучу персонажей с чем-то вроде
REPLACE(TRANSLATE('source string','ABCD','XXXX'),'X','')
Некоторые более интересные из них , а также, как
CONCAT_WS
иSTRING_AGG
что, вероятно , стоит посмотреть , как хорошо.источник
Святая корова, я обнаружил чудо
PARSENAME
( SQL 2012 или выше ).Функция была построена так, чтобы изолировать части имени объекта, например
servername.dbname.dbo.tablename
, но она работает для любых значений, разделенных точками. Просто запомните, это считается справа , а не слева:Если у вас меньше 4 значений, разделенных точками, он вернется
NULL
к остатку (но он все равно будет считаться справа налево ):Вот где магия приходит: комбинируйте ее с
STRING_SPLIT
(2016 или выше), чтобы создать таблицы из нескольких столбцов в памяти !!Старый и разоренный:
Новая жара:
Очевидно, что ваши фактические сбережения зависят от размера и содержания таблицы и от того, как именно вы ее используете.
Обратите внимание , что если ваши поля являются постоянной шириной, вы , вероятно , лучше использовать
LEFT
иRIGHT
отделить их вместоPARSENAME
(не только потому , что имена функций короче, но и потому , что вы можете устранить сепараторы полностью).источник
Еще пару несвязанных трюков, которые я видел и хотел сохранить:
GO #
чтобы повторить блок определенное количество раз .Увидел этот хитрый трюк на превосходном ответе Пола .
Это, конечно, сбрасывает все переменные счетчика в блоке, поэтому вам придется взвесить это с
WHILE
циклом илиx: ... GOTO x
циклом.SELECT TOP ... FROM systypes
Из того же вопроса, что и у Павла, Анудж Трипати использовал следующий трюк :
или, как предполагает pinkfloydx33 в комментариях:
Обратите внимание , это не зависит от какого - либо из фактического содержания в
systypes
, так что вид системы существует (что он делает в каждой базе данных MS SQL), и содержит , по меньшей мере , 10 строк (это выглядит , чтобы содержать 34, для большинства последних версий SQL ). Я не смог найти никаких системных представлений с более короткими именами (которые не требовалиsys.
префикса), так что это может быть идеальным.источник
Смотрите этот вопрос на dba.stackexchange для некоторых интересных идей по добавлению числового столбца к результату STRING_SPLIT.
Учитывая строку как
'one,two,three,four,five'
, мы хотим получить что-то вроде:Ответ, использование
ROW_NUMBER()
и порядок Пера Джо ОббишаNULL
или константа:Согласно ответу Пола Уайта, используйте
SEQUENCE
:Последовательности представляют собой интересные постоянные объекты; Вы можете определить тип данных, минимальное и максимальное значение, интервал и будет ли он переноситься в начало:
За ответ Biju JOSE, вы можете использовать в
IDENTITY()
функцию (которая не так же , как вIDENTITY
собственности в сочетании с вкладышем:Обратите внимание, что последние два параметра
IDENTITY(INT,1,1)
являются необязательными и по умолчанию равны 1, если исключены.источник
ORDER BY
если мне это сойдет с рук (см. Мой ответ, например, Toasty, Burnt, Brulee ).Просто обнаружил, что вы можете использовать цифры для одного символа,
REPLACE
чтобы исключить кавычки :Это потому, что
REPLACE
делает неявное преобразование в строку.Оба выдают одинаковый результат:
источник
_ и # являются действительными псевдонимами. Я использую их с CROSS APPLY, чтобы они выглядели как возвращаемые столбцы, как часть предложения FROM, например
Мне нравится, когда единственной целью CROSS APPLY является вычисление выражения.
В этом отношении использование APPLY для вычисления подвыражений - это отличный способ сделать ваш код более сухим (и более коротким). Из того, что я видел в планах выполнения, этот подход не требует дополнительных затрат. Компилятор выясняет, что вы просто что-то вычисляете, и обрабатывает это как любое другое выражение.
источник