Поради щодо гольфу в T-SQL


16

Які загальні поради щодо гольфу в T-SQL? Я шукаю ідеї, які взагалі можуть бути застосовані для кодування проблем із гольфом, які принаймні дещо характерні для T-SQL. Будь ласка, опублікуйте одну пораду на відповідь.

Дякую Маркогу за оригінальну ідею. :)


підказка - використовуйте іншу мову для гольфу. Відповіді на Sql зазвичай отримують дуже мало або взагалі немає оновлень.
t-clausen.dk

Відповіді:


16

Мій загальний мішок хитрощів:

  • @ є дійсною змінною в t-sql.
  • T-sql 2012 додав iifвипадок випадку стилю VB. Це майже завжди коротше, ніж еквівалент if else.
  • \є корисним способом ініціалізації числа як 0 у грошовій формі. Ви можете перетворити значення в float, додавши e. наприклад, 4eабо \kяка встановить k до значення 0,00 грошей.
  • rCTEздається, найкращий спосіб створити таблицю чисел, що не перевищує 100 записів. Навіть коротше, ніж використання spt_values. Якщо вам потрібно більше 100, перехрестіть і додайте їх.
  • += та інші складні оператори були додані в 2008 році. Використання їх дозволяє економити кілька символів.
  • Літерали, як правило, досить хороший роздільник для спокійних цілей. Вам рідко потрібен пробіл чи а ;.
  • Використовуйте ANSI SQL приєднується, якщо вони вам потрібні. Select*from A,B where conditionкоротше, ніжselect*from A join b on condition
  • Якщо ви можете бути впевнені, що ваш цикл while зробить першу ітерацію, найкраще переписати його як gotoцикл стилю do- while.
  • STR()це найкоротша функція перетворення int у рядок. Якщо ви робите більше однієї конверсії або, можливо, знадобиться сформувати безліч різних типів даних, врахуйте concatфункцію. Наприклад 'hello'+str(@), коротше concat('hello',@), але hello+str(@)+str(@a)довшеconcat('hello',@,@a)

Наприклад, ці два семантично рівнозначні.

while @<100begin/*code*/set @+=1 end
s:/*code*/set @+=1if @<100goto s

Ви можете використовувати Valuesдля створення таблиці або підзапиту. Це дійсно буде корисною, якщо вам потрібно кілька постійних рядів.


Для мене $ трохи очевидніше, ніж \ ініціалізувати число як 0 у грошовій формі. YMMV
користувач1443098

5

Стиснення коду за допомогою SQL

SQL є багатослівним, набирає високих показників, і стільки, скільки ми любимо, SELECT FROM WHEREкоштував 23 байти з кожним використанням. Ви можете стиснути ці та інші повторені слова або цілі фрагменти коду. Це зменшить граничну вартість повторного коду до 1 байта! *

Як це працює:

  • Змінна оголошується і присвоюється стисненому коду SQL
  • Таблиця змінює змінну. Кожен рядок визначає змінну.
  • Змінена змінна виконується.

Проблема:

Попередня вартість близько 100 байт, і кожен рядок таблиці заміни коштує ще 6 байт. Така логіка не буде дуже ефективною, якщо ви не працюєте з великою кількістю коду, який ви не можете відрізати, або виклик на основі стиснення.

Ось приклад

Завдання полягає в тому, щоб отримати останні 10 кратних 2,3 і 5, що ведуть до n. Скажімо, це ( 343 байти в гольф ) - найкраще рішення, з яким я міг придумати:

WITH x AS(
    SELECT 99 n
UNION ALL 
    SELECT n-1
    FROM x
    WHERE n>1
)
SELECT w.n,t.n,f.n
FROM
    (SELECT n, ROW_NUMBER()OVER(ORDER BY n DESC)r
     FROM x WHERE n%2=0
    )w
,
    (SELECT n, ROW_NUMBER()OVER(ORDER BY n DESC)r
     FROM x WHERE n%3=0
    )t
,   (SELECT n, ROW_NUMBER()OVER(ORDER BY n DESC)r
     FROM x WHERE n%5=0
    )f
WHERE w.r=t.r AND w.r=f.r AND w.r<11
ORDER BY 1

Приклад після стискання коду

Це виконує той самий код, що і вище, ~ 302 байти в гольф .

DECLARE @a CHAR(999)='
WITH x AS(!99n UNION ALL !n-1 @x#n>1)
!w.n,t.n,f.n@$2=0)w,$3=0)t,$5=0)f
#w.r=t.r AND w.r=f.r AND w.r<11^1'

SELECT @a=REPLACE(@a,LEFT(i,1),SUBSTRING(i,2,99))
FROM(VALUES
  ('$(!n,ROW_NUMBER()OVER(^n DESC)r@x#n%'),
  ('! SELECT '),
  ('@ FROM '),
  ('# WHERE '),
  ('^ ORDER BY ')
)x(i)

EXEC(@a)

Відмінна стратегія, що стиль мультизаміни може бути корисним і в більш звичайних сценаріях.
BradC

1
Після деякого тестування я визначив, що якщо у вашому списку замін міститься 7 або менше елементів, ви будете зберігати байти, роблячи SELECT @=REPLACE(@,i,j)FROM(VALUES(...)x(i,j)замість того, щоб використовувати один стовпчик з LEFT()і SUBSTRING(). Якщо у вас є 8 і більше, то уникати зайвих котирувань і коми - це хороший компроміс.
BradC

Насправді за 4 або менше замін ви заощадите байти старомодноSET @=REPLACE(REPLACE(REPLACE(...
BradC

4

Ось кумедна. Це перетворить значення в стовпці в один кордон.

EDIT: Дякую за коментарі. Схоже, найкоротший спосіб згуртування без тегів XML:

SELECT (SELECT column1+''
FROM table
ORDER BY column1
FOR XML PATH(''))

Примітка: якщо XML є дійсним висновком, ви можете опустити зовнішній вибір і паролі. Крім того column1+'', працює лише для рядків. Для типів номерів найкраще це зробитиcolumn1+0


1
Насправді вона повернеться <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 :(
Якоб

1
Зверніть увагу, ви можете зробити це коротше. Ltrimне потрібно, оскільки select (select ... for xml path ('')) повертає nvarchar(max). Крім того, для вирішення речі стовпця просто використовуйте вираз, що не мутує. Для числових цифр, які ви можете зробити v+0, для рядків додайте порожню рядок і т. Д. Хоча я і справді не вважаю це порадою для гольфу, це, на жаль, реальність того, як писати запити на сервері sql.
Майкл Б

3

У T-SQL можна використовувати деякі побітові оператори .

Я не маю конкретного прикладу, але я вважаю, що це добре відомий факт при гольфінгу в T-SQL.


1
Це дуже справедливо. Замість того, щоб писати умову типу x=0 or y=0, ви можете написати це як логічно еквівалент, x|y=0що економить досить багато байтів!
Майкл Б


3

Наукове позначення - це коротший метод вираження дуже великих і дуже малих чисел, наприклад select 1000000000= select 1E9і select 0.000001= select 1E-6.


2

Майкл Б згадав про використання рекурсивного CTE для таблиці таблиць , але не показав приклад. Ось версія MS-SQL, яку ми опрацювали в цій іншій темі :

--ungolfed
WITH t AS (
    SELECT 1 n 
    UNION ALL 
    SELECT n + 1
    FROM t 
    WHERE n < 99)
SELECT n FROM t

--golfed
WITH t AS(SELECT 1n UNION ALL SELECT n+1FROM t WHERE n<99)SELECT n FROM t

Зауважте, що ви можете змінити початкове значення ( 1 n), інтервал ( n + 1) та кінцеве значення ( n < 99).

Якщо вам потрібно більше 100 рядків, вам потрібно буде додати option (maxrecursion 0):

WITH t AS(SELECT 0n UNION ALL SELECT n+1FROM t WHERE n<9999)
SELECT n FROM t option(maxrecursion 0)

або приєднати rCTE до себе:

WITH t AS(SELECT 0n UNION ALL SELECT n+1FROM t WHERE n<99)
SELECT 100*z.n+t.n FROM t,t z

Хоча цей останній не гарантовано повертається в числовому порядку без знака "an" ORDER BY 1


2

Використовуйте стиснення GZIP для дуже довгих рядків!

Тому я знав, що SQL 2016 додав COMPRESSфункцію (і DECOMPRESSфункцію), яка (нарешті) приносить можливість GZIP рядка або двійкової.

Проблема полягає в тому, що не відразу зрозуміло, як скористатися цим для гольфу; COMPRESSможе приймати рядок, але повертає a VARBINARY, яке коротше в байтах (коли він зберігається в VARBINARYполі SQL ), але довше в символах (неочищений шістнадцятковий).

Я грав із цим раніше, але нарешті зміг скласти робочу версію, грунтуючись на цій старій відповіді на ТА . Ця публікація не використовує нові функції GZIP, але вона конвертує a VARBINARYв кодовану рядок Base-64. Нам просто потрібно було вставити нові функції в потрібне місце і трохи розіграти їх.

Ось код, за допомогою якого ви можете перетворити свою дуже довгу рядок у стиснуту рядок, кодовану Base-64:

DECLARE @s VARCHAR(MAX)='Your really long string goes right here'
SELECT CONVERT(VARCHAR(MAX),(SELECT CONVERT(VARBINARY(MAX),COMPRESS(@s))
       FOR XML PATH(''),BINARY BASE64))

Візьміть висновок і використовуйте його у своєму коді замість початкового довгого рядка разом із:

--To use your compressed string and return the original:
DECLARE @e VARCHAR(MAX)='H4sIAAAAAAAEAIvMLy1SKEpNzMmpVMjJz0tXKC4pygRS6fmpxQpFmekZJQoZqUWpAGGwW5YnAAAA'
SELECT CAST(DECOMPRESS(CAST(@e as XML).value('.','varbinary(max)'))AS varchar(max))

Тож замість вашого початкового коду ( 1471 байт )

SELECT'Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal. Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this. But, in a larger sense, we can not dedicate — we can not consecrate — we can not hallow — this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us — that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion — that we here highly resolve that these dead shall not have died in vain — that this nation, under God, shall have a new birth of freedom — and that government of the people, by the people, for the people, shall not perish from the earth.'

у вас би це було ( 1034 байти ):

SELECT CAST(DECOMPRESS(CAST('H4sIAAAAAAAEAGVUW47bMAy8Cg/g5hD9aLFA0a8C/aYt2hZWEVNJjpGT5LodinE2i/0JIouPmeFQP3QrVCctQpwDVblKpptwqcSLkt3O3FbBeSy6LWujWUtbSTO1NVaaNLeYJbeBmLLslLlFzYNdTBKvEihm+hVHKe029CZBQpy44aYpighdil60RsvDmRtxSnQGEAasqUiPlX8bpxP91p126TeSF168PtNiYTTFa0y0cxmoSQWwhfZVDL8XPsBpAZLb40hVX9B+QgganCkp6kgOW5ET/fXmZ2mmwdF45NaSfJujpEA6ezfg6PErX8FDz2KEj9pIvUBJ63/E92xoBO3xP3Oi8iBxSTyJKY9ArQJSSiAltFhp8IuFEuBXL/TClc7RhmaXJ3prhJFxarq4KHNsvb6RtikcOkHhuuoGLkH7nE/0fcOIu9SJy4LAKrnKYKGmUdb2Qe3++hXSVpnKl+8rpoxh3t1HC9yVw4n+wA9jMVYwwGC4D3xBGOIY89rKtiwJwzINhkPfow0cAagzY8aj4sZMfFG1n90IKnEIZoEgrfDUvOmuBXT3COulaMM0kCieEdgNUOQsZ9gYEB4K8e0BYNwgbHNm2KBik4LCHgmhbxSigz1mYKPcane/Uxyo9D0bDN8oL0vS5/zYlC3DF7Gu+Ay872gQp9U7mDCzb2jPWN0ZaGJKwOJZx3QD9SvD6uEA4l2feHrvnv9lS93ojeu7ScHAAVFGme3tQOr94eGiZwuHSVeFduKDM70avwscZAtd++er+sqrp068VTf5C63D4HBdRfWtvwxcsYq2Ns8a96dvnTxMD7JYH0093+dQxcFU897DhLgO0V+RK0gdlbopj+cCzoRGPxX+89Se5u/dGPtzOIO5SAD5e3drL7LAfiXDyM13HE+d6CWZY26fjr7ZH+cPgFhJzPspK+FpbuvpP9RXxXK3BQAA'as XML).value('.','varbinary(max)'))AS varchar(max))

Дивіться цю відповідь, яка врятувала мені майже 200 байт.

Я не займався математикою, але очевидно, що через накладні витрати це буде ефективно лише для надзвичайно довгих струн. Напевно, є й інші місця, якими не можна користуватися; Я вже виявив, що ви маєте SELECTце, ви не можете PRINTцього, інакше ви отримаєте:

Xml data type methods are not allowed in expressions in this context.

EDIT : Скорочений варіант коду розпаковувати, люб'язно @digscoop :

Збережіть 10 байт, змінивши зовнішнє CASTна неявне перетворення за допомогою CONCAT:

SELECT CONCAT('',DECOMPRESS(CAST('encoded_string_here'as XML).value('.','varbinary(max)')))

Ви також можете оголосити змінну типу XMLзамість VARCHAR(MAX), а також зберегти на внутрішній CAST:

DECLARE @ XML='encoded_string_here'
SELECT CONCAT('',DECOMPRESS(@.value('.','varbinary(max)')))

Це трохи довше саме по собі, але якщо вам це потрібно в змінній з інших причин, то це може допомогти.


Приємно, я не знаю SQL, але це виглядає все ще круто
MilkyWay90,

1

Кілька думок про створення та використання таблиць для викликів:

1. Введення SQL можна здійснити через попередньо існуючу таблицю

Коди Гольф Методи введення / виведення :

SQL можуть приймати дані з іменованої таблиці

Створення та заповнення цієї таблиці за допомогою вхідних значень не враховується до загального байту, ви можете припустити, що вона вже є.

Це означає, що ваші обчислення можуть виводитись за допомогою простого SELECT з таблиці введення:

SELECT 2*SQRT(a)FROM t

2. Якщо можливо, насправді взагалі не створюйте таблицю

Замість (69 байт):

CREATE TABLE t(b INT)
INSERT t VALUES(7),(14),(21),(99)
SELECT b FROM t

Просто зробіть (43 байти):

SELECT b FROM(VALUES(7),(14),(21),(99))t(b)

3. Якщо можливо, створіть таблицю SELECT INTO

Замість (39 байт):

CREATE TABLE t(p INT)
INSERT t VALUES(2)

Зробіть це (17 байт):

SELECT 2 p INTO t

4: Розгляньте розміщення кількох стовпців разом

Ось дві варіанти, які повертають однаковий вихід:

SELECT a,b FROM
(VALUES('W','Bob'),('X','Sam'),('Y','Darla'),('Z','Elizabeth'))t(a,b)

SELECT LEFT(a,1),SUBSTRING(a,2,99)FROM
(VALUES('WBob'),('XSam'),('YDarla'),('ZElizabeth'))t(a)

Після деякого тестування верхня версія (декілька стовпців) здається коротшою із 7 або меншими рядками , нижня (завдяки лівому та підписному) коротша на 8 чи більше рядків . Ваш пробіг може змінюватися в залежності від ваших точних даних.

5: Використовуйте REPLACE і EXEC для дуже довгих послідовностей тексту

У відмінні відмінної відповіді комфортнодреї , якщо у вас є 15 і більше значень , використовуйте REPLACEсимвол, щоб позбутися від повторних '),('роздільників між елементами:

114 символів:

SELECT a FROM(VALUES('A'),('B'),('C'),('D'),('E'),('F'),('G'),('H')
,('I'),('J'),('K'),('L'),('M'),('N'),('O'))t(a)

112 символів:

DECLARE @ CHAR(999)=REPLACE('SELECT a FROM(VALUES(''
 A-B-C-D-E-F-G-H-I-J-K-L-M-N-O''))t(a)','-','''),(''')EXEC(@)

Якщо ви вже використовуєте динамічний SQL з інших причин (або маєте кілька замін), то поріг, де це варто, значно нижчий.

6: Використовуйте SELECT з іменованими стовпцями, а не купу змінних

Натхненний чудовою відповіддю jmlt тут , повторно використовуйте рядки через SELECT:

SELECT a+b+a+b+d+b+b+a+a+d+a+c+a+c+d+c+c+a+a
FROM(SELECT'Hare 'a,'Krishna 'b,'Rama 'c,'
'd)t

повертає

Hare Krishna Hare Krishna 
Krishna Krishna Hare Hare 
Hare Rama Hare Rama 
Rama Rama Hare Hare 

(Для MS SQL я змінив \tдо повернення в лінії, і змінив CONCAT()на , +щоб зберегти байти).


1

Позначте свій код для виділення синтаксису T-SQL

Замість просто:

CREATE TABLE t(b INT)
INSERT t VALUES(7),(14),(21),(99)
SELECT b FROM t

Додайте такий тег мови:

<!-- language: lang-sql -->

    CREATE TABLE t(b INT)
    INSERT t VALUES(7),(14),(21),(99)
    SELECT b FROM t

і результат буде:

CREATE TABLE t(b INT)
INSERT t VALUES(7),(14),(21),(99)
SELECT b FROM t

1

Скористайтеся новими можливостями / функціями в MS SQL 2016 та SQL 2017

Якщо у вас немає локальних копій, з якими можна працювати, ви можете грати в Інтернеті за допомогою Провідника даних StackExchange (SQL 2016) або з dbfiddle.uk (SQL 2016 або SQL "vNext").

STRING_SPLIT ( SQL 2016 та новіших версій )

SELECT *
FROM STRING_SPLIT('one,two,three,four,five',',')

Якщо вам потрібно встановити псевдонім таблиці або посилатися на назву стовпця:

SELECT t.value
FROM STRING_SPLIT('one,two,three,four,five',',')t

TRIM ( SQL 2017 або новішої версії )

Коротше RTRIM()і, звичайно, коротше LTRIM(RTRIM()).

Також є можливість видалити інші символи чи набори символів з початку чи кінця:

SELECT TRIM('sq,0' FROM 'SQL Server 2000')

повертає L Server 2

TRANSLATE ( SQL 2017 або новішої версії )

TRANSLATEдозволяє замінити кілька символів за один крок, а не купу вкладених REPLACEвисловлювань. Але не святкуйте занадто багато, це лише замінює окремих окремих символів різними окремими символами.

SELECT TRANSLATE('2*[3+4]/{7-2}', '[]{}', '()()');

Кожен символ другого рядка замінюється відповідним символом у 3-му рядку.

Схоже, ми могли б усунути купу персонажів із чимось подібним REPLACE(TRANSLATE('source string','ABCD','XXXX'),'X','')


Ще кілька цікавих, як, наприклад, CONCAT_WSі STRING_AGGякі, ймовірно, варто також подивитися.


1

Свята корова, я виявив диво PARSENAME( SQL 2012 або вище ).

Функція була побудована для ізоляції частин назви об'єкта типу servername.dbname.dbo.tablename, але вона працює для будь -яких значень, розділених крапками. Просто пам’ятайте, що вона рахується справа , а не зліва:

SELECT PARSENAME('a.b.c.d',1),      -- d
       PARSENAME('a.b.c.d',2),      -- c
       PARSENAME('a.b.c.d',3),      -- b
       PARSENAME('a.b.c.d',4)       -- a

Якщо у вас менше 4-х розділених значень, воно повернеться NULLна залишок (але він все одно рахується праворуч ліворуч ):

SELECT PARSENAME('a.b',1),      -- b
       PARSENAME('a.b',2),      -- a
       PARSENAME('a.b',3),      -- NULL
       PARSENAME('a.b',4)       -- NULL

Ось, звідки входить магія: комбінуйте її з STRING_SPLIT(2016 або новішою версією), щоб скласти багатоколонкові таблиці в пам'яті !!

Старий і розбитий:

SELECT a,b,c FROM
(VALUES('Bob','W','Smith'),
       ('Sam','X','Johnson'),
       ('Darla','Y','Anderson'),
       ('Elizabeth','Z','Turner'))t(a,b,c)

Нова гарячість:

SELECT PARSENAME(value,3)a,PARSENAME(value,2)b,PARSENAME(value,1)c
FROM string_split('Bob.W.Smith-Sam.X.Johnson-Darla.Y.Anderson-Elizabeth.Z.Turner','-')

Очевидно, що фактична економія залежить від розміру та вмісту таблиці та того, як саме ви її використовуєте.

Зауважте, що якщо ваші поля постійної ширини, вам, мабуть, краще використовувати їх LEFTі RIGHTрозділяти їх замість PARSENAME(не тільки тому, що назви функцій коротші, а й тому, що ви можете повністю усунути роздільники).


Я не впевнений, коли з'явився PARSENAME, але є статті, що описують це з 2003 року
t-clausen.dk

1

Ще кілька незв'язаних хитрощів, які я побачив і хотів зберегти:

  1. Використовуйте GO #для повторення блоку певну кількість разів .

Цей розумний трюк побачив у відмінній відповіді Павла .

PRINT'**********'
GO 10

Це, звичайно, скине будь-які змінні лічильника в блоці, тому вам доведеться зважувати це на WHILEциклі чи x: ... GOTO xциклі.

  1. SELECT TOP ... FROM systypes

З того ж питання, що й у Павла, Ануй Трипаті застосував таку хитрість :

SELECT TOP 10 REPLICATE('*',10) FROM systypes

або, як запропонував pinkfloydx33 у коментарях:

SELECT TOP 10'**********'FROM systypes

Зверніть увагу , це не залежить від будь - якої з фактичного змісту вsystypes , так що вид системи існує (що він робить в кожній базі даних MS SQL), і містить , щонайменше , 10 рядків (це виглядає , щоб утримувати 34, для більшості останніх версій SQL ). Я не міг знайти жодних системних представлень із короткими іменами (для яких не потрібен sys.префікс), тому це може бути ідеальним.


1

Побачити це запитання на dba.stackexchange, щоб отримати цікаві ідеї щодо додавання стовпця цифр до результату STRING_SPLIT.

Враховуючи такий рядок 'one,two,three,four,five', ми хочемо отримати щось на зразок:

value   n
------ ---
one     1
two     2
three   3
four    4
five    5
  1. Відповідь Джо Оббіша, використання ROW_NUMBER()та замовлення на NULLабо постійну:

    SELECT value, ROW_NUMBER() OVER(ORDER BY (SELECT 1))n
    FROM STRING_SPLIT('one,two,three,four,five',',')
    
  2. Відповідь Пола Уайта використовуйтеSEQUENCE :

    CREATE SEQUENCE s START WITH 1
    SELECT value, NEXT VALUE FOR s 
    FROM STRING_SPLIT('one,two,three,four,five', ',')
    

Послідовності - цікаві стійкі об’єкти; ви можете визначити тип даних, значення min та max, інтервал та чи завершується він до початку:

    CREATE SEQUENCE s TINYINT;     --Starts at 0
    CREATE SEQUENCE s MINVALUE 1;  --Shorter than START WITH
    SELECT NEXT VALUE FOR s        --Retrieves the next value from the sequence
    ALTER SEQUENCE s RESTART;      --Restarts a sequence to its original start value
  1. За відповідь Biju JOSE, ви можете використовувати в IDENTITY() функцію (яка НЕ так само , як в IDENTITY власності в поєднанні з вкладишем:

    SELECT value v,IDENTITY(INT) AS n
    INTO t
    FROM STRING_SPLIT('one,two,three,four,five',',')
    
    SELECT * FROM t
    

Зауважте, що останні два параметри в IDENTITY(INT,1,1)опції необов’язкові, а за замовчуванням дорівнює 1, якщо вони виключені.


проблема полягає в тому, що STRING_SPLIT не гарантує жодного замовлення на повернення. Ви можете подумати, що він завжди буде повертати набір рядків у порядку лексем у вихідному рядку. Дійсно, це може навіть зробити! Однак гарантії в документах немає. це добре, якщо вам не байдуже замовлення. Але якщо це зробити (наприклад, розбирати рядок у форматі CSV), є проблема.
користувач1443098

1
@ user1443098 Я, зрештою, погоджуюся з вами в контексті рекомендування коду для ділових цілей, як ми могли бачити на dba.SE. Але щодо проблем, що стосуються PPCG, мої стандарти дещо інші; якщо під час тестування мій код повертає рядки в потрібному мені порядку, то я зберігаю байти там, де можу. Подібно тому, як я залишу йогоORDER BY якщо зможу піти з ним (див. Мою відповідь, наприклад, Тості, Бернт, Брюлі ).
БредК

1

Щойно виявлено, що ви можете використовувати цифри для однозначного символу REPLACEдля усунення лапок :

--44 bytes
PRINT REPLACE('Baby Shark******','*',' doo')

--42 bytes
PRINT REPLACE('Baby Shark000000',0,' doo')

Це відбувається тому REPLACE що відбувається неявне перетворення в рядок.

Обидва отримують однаковий вихід:

Baby Shark doo doo doo doo doo doo

0

_ і # - дійсні псевдоніми. Я використовую їх із CROSS APPLY, щоб вони з'явилися, що стовпці, які він повертає, є частиною пункту FROM, наприклад

SELECT TOP 10 number, n2
FROM master.dbo.spt_values v
CROSS APPLY (SELECT number*2 n2) _

Мені подобається це, коли єдина мета CROSS APPLY - обчислити вираз.

З цього приводу використання APPLY для обчислення підвиразів є акуратним способом зробити свій код DRY-er (і коротше). З того, що я бачив у планах виконання, цей підхід не додає додаткових витрат. Компілятор з'ясовує, що ви просто щось обчислюєте, і ставиться до цього, як до будь-якого іншого виразу.


Я вважаю, що крос застосовується довго, дуже важко знайти корисну ситуацію, використовуючи крос застосувати, не знаходячи іншого коротшого методу
t-clausen.dk

Гаразд - скорочуйте приклад, наведений вище!
користувач1443098

ВИБІР ТОП 10 номер, номер * 2 n2 ВІД master.dbo.spt_values ​​v
t-clausen.dk

Я маю на увазі, зберігаючи приєднання. До речі, щойно ви створюєте xml запити, CROSS APPLY може стати єдиним способом це зробити, оскільки у підзапиті може бути стовпчиків.
користувач1443098

Підвибір коротший, ніж поперечне застосування: ВИБІРТЕ верхню 10 * ВІД (ВИБІР номер n, число * 2n2 ВІД головного..spt_values) x
t-clausen.dk
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.