Dicas para jogar golfe no T-SQL

16

Que dicas gerais você tem para jogar golfe no T-SQL? Estou procurando idéias que possam ser aplicadas para codificar problemas de golfe em geral que sejam pelo menos um pouco específicos para o T-SQL. Poste uma dica por resposta.

Obrigado a Marcog pela ideia original. :)

Michael B
fonte
uma dica - use um idioma diferente para jogar golfe. As respostas SQL geralmente recebem muito poucas ou nenhuma votação.
t-clausen.dk

Respostas:

16

Minha sacola geral de truques ::

  • @ é uma variável válida no t-sql.
  • O T-sql 2012 adicionou iifuma declaração de caso no estilo VB. Isso é quase sempre mais curto que um equivalente if else.
  • \é uma maneira útil de inicializar um número como 0 em um tipo de dinheiro. Você pode converter um valor em flutuante adicionando e. por exemplo, 4eou \kque definirá k como o valor 0,00 dinheiro.
  • rCTEparece ser a melhor maneira de criar uma tabela numérica com menos de 100 entradas. Ainda mais curto do que usar spt_values. Se você precisar de mais de 100, junte-se a cruz e adicione-os.
  • += e outros operadores compostos foram adicionados em 2008. Use-os para salvar alguns caracteres.
  • Os literais são geralmente um delimitador suficientemente bom para propósitos de alias. Você raramente precisa de um espaço ou um ;.
  • Use junções ANSI SQL, se necessário. Select*from A,B where conditioné mais curto queselect*from A join b on condition
  • Se você tiver certeza de que o loop while fará a primeira iteração, é melhor reescrevê-lo como um gotoloop de estilo do while.
  • STR()é a função mais curta para transformar um int em uma string. Se você estiver fazendo mais de uma conversão ou precisar concatinar vários tipos de dados diferentes, considere a concatfunção Por exemplo, 'hello'+str(@)é mais curto que concat('hello',@), mas hello+str(@)+str(@a)é mais longo queconcat('hello',@,@a)

Por exemplo, esses dois são semanticamente equivalentes.

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

Você pode usar Valuespara criar uma tabela ou subconsulta. Isso só será realmente um benefício se você precisar de algumas linhas constantes.

Michael B
fonte
Para mim, $ é um pouco mais óbvio do que \ inicializar um número como 0 em um tipo de dinheiro. YMMV
user1443098
5

Compactação de código usando SQL

O SQL é prolixo, tem pontuações altas e, tanto quanto nós os amamos, SELECT FROM WHEREcusta 23 bytes a cada uso. Você pode compactar essas e outras palavras repetidas ou trechos de código inteiros. Isso diminuirá o custo marginal do código repetido para 1 byte! *

Como isso funciona:

  • Uma variável é declarada e recebe o código SQL compactado
  • Uma tabela modifica a variável. Cada linha esvazia a variável.
  • A variável modificada é executada.

O problema:

O custo inicial é próximo a 100 bytes e cada linha na tabela de substituição custa outros 6 bytes. Esse tipo de lógica não será muito eficaz, a menos que você esteja trabalhando com muito código que não pode reduzir ou o desafio é baseado em compactação.

Aqui está um exemplo

O desafio é obter os últimos 10 múltiplos de 2,3 e 5 até n. Digamos que essa ( 343 bytes de golfe ) seja a melhor solução que eu poderia encontrar:

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

Exemplo após o código ser compactado

Isso executa o mesmo código acima, é ~ 302 bytes jogados .

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)
confortavelmente
fonte
Ótima estratégia, esse estilo de substituição múltipla também pode ser útil em cenários mais convencionais.
BradC
11
Após alguns testes, determinei que, se sua lista de substituições tiver 7 ou menos itens, você salvaria bytes fazendo isso em SELECT @=REPLACE(@,i,j)FROM(VALUES(...)x(i,j)vez de usar uma única coluna com LEFT()e SUBSTRING(). Se você tiver 8 ou mais, evitar cotações e vírgulas extras é uma boa opção.
BradC
Na verdade, para 4 ou menos substituições, você salvar bytes com um antiquadoSET @=REPLACE(REPLACE(REPLACE(...
BradC
4

Aqui está uma pergunta engraçada. Isso converterá os valores em uma coluna em uma única tupla.

EDIT: Obrigado pelos comentários. Parece que a maneira mais curta de acumular sem as tags XML é:

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

Nota: se XML for uma saída válida, você poderá omitir a seleção externa e parens. Também column1+''funciona apenas para strings. Para tipos de números, é melhor fazercolumn1+0

confortavelmente
fonte
11
Na verdade, ele retornará <column_name>value1</column_name><column_name>value2</column_name>.... Para obter um CSV de uma coluna, você pode DECLARE @ VARCHAR(MAX)='';SELECT @+=column_name+',' FROM table_name;SELECT @(obrigado pela primeira dica de @ MichaelB) que retornará value1,value2,.... No entanto, é na verdade 9 caracteres mais do que o seu truque XML :(
Jacob
11
Observe que você pode tornar isso mais curto. Ltrimnão é necessário, pois select (select ... for xml path ('')) retorna um nvarchar(max). Além disso, para resolver o problema da coluna, basta usar uma expressão não mutante. Para números, você pode fazer v+0, para string adicionar string vazia, etc. Embora eu realmente não considere isso uma dica de golfe, isso é apenas uma realidade de como escrever consultas no servidor sql.
Michael B
3

É possível usar alguns operadores bit a bit no T-SQL .

Não tenho um exemplo concreto, mas acredito que é um fato importante saber jogar golfe no T-SQL.

Jacob
fonte
11
Isso é muito válido. Em vez de escrever uma condição como x=0 or y=0, você pode escrever isso como o equivalente logicamente x|y=0que economiza alguns bytes!
22640 Michael Jackson B
3

Imprimir em vez de Selecionar

É simples assim! Então, aqui está um poliglota T-SQL / Python:

print'Hello, World!'

Experimente online

mbomb007
fonte
3

A notação científica é um método mais curto para expressar números muito grandes e muito pequenos, por exemplo, select 1000000000= select 1E9e select 0.000001= select 1E-6.

naXa
fonte
2

Michael B mencionou o uso de um CTE recursivo para uma tabela numérica , mas não mostrou um exemplo. Aqui está uma versão do MS-SQL que elaboramos neste outro segmento :

--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

Observe que você pode alterar o valor inicial ( 1 n), o intervalo ( n + 1) e o valor final (n < 99 ).

Se você precisar de mais de 100 linhas, precisará adicionar option (maxrecursion 0):

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

ou junte o rCTE a si mesmo:

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

Embora não seja garantido que este último retorne em ordem numérica sem um ORDER BY 1

BradC
fonte
2

Use a compressão GZIP para seqüências muito longas!

Então, eu sabia que o SQL 2016 adicionou uma COMPRESSfunção (e umDECOMPRESS função), que (finalmente) traz a capacidade de GZIP uma string ou binário.

O problema é que não está claro imediatamente como tirar proveito disso para o golfe; COMPRESSpode pegar uma string, mas retorna a VARBINARY, que é mais curto em bytes (quando armazenado em um VARBINARYcampo SQL ), mas é mais longo em caracteres (hexadecimal bruto).

Já brinquei com isso antes, mas finalmente consegui montar uma versão funcional, com base nessa resposta antiga no SO . Essa publicação não usa as novas funções GZIP, mas converte umVARBINARY em uma string codificada em Base-64. Nós apenas precisamos inserir as novas funções no lugar certo e aprimorar um pouco.

Aqui está o código que você pode usar para converter sua cadeia muito longa na cadeia compactada codificada em 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))

Pegue a saída e use-a no seu código no lugar da cadeia longa original, junto com:

--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))

Então, em vez do seu código original ( 1471 bytes )

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.'

você teria isso ( 1034 bytes ):

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))

Veja esta resposta que me salvou quase 200 bytes.

Eu não fiz as contas, mas claramente devido à sobrecarga, isso só será eficaz para seqüências extremamente longas. Provavelmente existem outros lugares onde isso não pode ser usado; Eu já descobri que você precisa SELECT, você não pode PRINT, caso contrário você obtém:

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

EDIT : Versão mais curta do código de descompactação, cortesia de @digscoop :

Salve 10 bytes alterando o externo CASTpara uma conversão implícita usando CONCAT:

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

Você também pode declarar uma variável do tipo em XMLvez de VARCHAR(MAX)e salvar no interior CAST:

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

Isso é um pouco mais longo por si só, mas se você precisar dele em uma variável por outros motivos, poderá ajudar.

BradC
fonte
Bom, eu não sei SQL, mas isso parece arrefecer ainda
MilkyWay90
1

Algumas reflexões sobre a criação e o uso de tabelas para desafios:

1. A entrada SQL pode ser obtida através de uma tabela pré-existente

Código Golf Métodos de Entrada / Saída :

SQLs podem receber entrada de uma tabela nomeada

Criar e preencher esta tabela com valores de entrada não conta para o total de bytes, você pode apenas assumir que ele já está lá.

Isso significa que seus cálculos podem gerar via SELECT simples da tabela de entrada:

SELECT 2*SQRT(a)FROM t

2. Se possível, não crie realmente uma tabela

Em vez de (69 bytes):

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

Basta fazer (43 bytes):

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

3. Se possível, crie a tabela com um SELECT INTO

Em vez de (39 bytes):

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

Faça isso (17 bytes):

SELECT 2 p INTO t

4: considere juntar várias colunas

Aqui estão duas variações que retornam a mesma saída:

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)

Após alguns testes, a versão superior (várias colunas) parece mais curta com 7 ou menos linhas , a versão inferior (devido a ESQUERDA e SUBSTRING) é mais curta com 8 ou mais linhas . Sua milhagem pode variar, dependendo dos dados exatos.

5: Use REPLACE e EXEC para sequências muito longas de texto

Na veia da excelente resposta de Drei , se você tiver 15 ou mais valores , use REPLACEum símbolo para se livrar da repetição'),(' separadores entre os elementos:

114 caracteres:

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

112 caracteres:

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(@)

Se você é usando SQL dinâmico por outros motivos (ou tiver várias substituições), o limite em que vale a pena é muito menor.

6: Use um SELECT com colunas nomeadas em vez de um monte de variáveis

Inspirado pela excelente resposta do jmlt aqui , reutilize as strings através de um 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

retorna

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

(Para o MS SQL I mudou o \tpara um regresso em-linha, e mudado CONCAT()para +salvar bytes).

BradC
fonte
1

Marque seu código para destacar a sintaxe T-SQL

Em vez de apenas:

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

Inclua uma tag de idioma como esta:

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

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

e o resultado será:

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

Aproveite os novos recursos / funções do MS SQL 2016 e SQL 2017

Se você não possui cópias locais para trabalhar, pode jogar online com o StackExchange Data Explorer (SQL 2016) ou com dbfiddle.uk (SQL 2016 ou SQL "vNext").

STRING_SPLIT ( SQL 2016 e posterior )

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

Se você precisar criar um alias na tabela ou consultar o nome da coluna:

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

TRIM ( SQL 2017 ou posterior )

Mais curto que RTRIM()e certamente menor queLTRIM(RTRIM()) .

Também tem uma opção para remover outros caracteres ou conjuntos de caracteres do começo ou do fim:

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

retorna L Server 2

TRADUZIR ( SQL 2017 ou posterior )

TRANSLATEpermite substituir vários caracteres em uma etapa, em vez de várias REPLACEinstruções aninhadas . Mas não comemoram muito muito, ele só substitui caracteres únicos individuais com diferentes personagens individuais.

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

Cada caractere na segunda cadeia é substituído pelo caractere correspondente na terceira cadeia.

Parece que poderíamos eliminar um monte de personagens com algo como REPLACE(TRANSLATE('source string','ABCD','XXXX'),'X','')


Alguns mais interessantes também, como CONCAT_WSe STRING_AGGque provavelmente valem uma olhada também.

BradC
fonte
1

Vaca sagrada, eu descobri a maravilha de PARSENAME( SQL 2012 ou superior ).

A função foi criada para isolar as partes de um nome de objeto servername.dbname.dbo.tablename, mas funciona para quaisquer valores separados por pontos. Lembre-se de que conta da direita , não da esquerda:

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

Se você tiver menos de 4 valores separados por pontos, ele retornará NULLpara o restante (mas ainda conta da direita para a esquerda ):

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

Aqui é onde entra a mágica: combine-a com STRING_SPLIT(2016 ou superior) para criar tabelas com várias colunas na memória !!

Velho e preso:

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

Nova gostosura:

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','-')

Claramente, suas economias reais dependem do tamanho e do conteúdo da tabela e de como exatamente você a está usando.

Observe que, se seus campos são de largura constante, é melhor usar LEFTe RIGHTsepará-los em vez de PARSENAME(não apenas porque os nomes das funções são mais curtos, mas também porque você pode eliminar completamente os separadores).

BradC
fonte
Não tenho certeza de quando PARSENAME foi lançado, mas há artigos descrevendo-o desde 2003
t-clausen.dk 30/03/19
1

Mais alguns truques não relacionados que vi e quis preservar:

  1. Use GO #para repetir um bloco um número específico de vezes .

Vi esse truque inteligente na excelente resposta de Paulo .

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

Obviamente, isso redefiniria quaisquer variáveis ​​de contador no bloco, portanto você teria que pesar isso em um WHILEloop ou x: ... GOTO xloop.

  1. SELECT TOP ... FROM systypes

Da mesma pergunta que a de Paulo acima, Anuj Tripathi usou o seguinte truque :

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

ou, como sugerido por pinkfloydx33 nos comentários:

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

Note que este não depende de qualquer um dos atuais conteúdos de systypes, apenas que existe a visão do sistema (o que faz em cada banco de dados MS SQL), e contém pelo menos 10 linhas (parece conter 34, para a maioria das versões recentes do SQL ) Não consegui encontrar nenhuma visualização do sistema com nomes mais curtos (que não exigiam um sys.prefixo), portanto isso pode ser o ideal.

BradC
fonte
1

Veja esta pergunta em dba.stackexchange para obter algumas idéias interessantes para adicionar uma coluna numérica a um resultado STRING_SPLIT.

Dada uma string como 'one,two,three,four,five', queremos obter algo como:

value   n
------ ---
one     1
two     2
three   3
four    4
five    5
  1. De acordo com a resposta de Joe Obbish, use ROW_NUMBER()e encomende por NULLou uma constante:

    SELECT value, ROW_NUMBER() OVER(ORDER BY (SELECT 1))n
    FROM STRING_SPLIT('one,two,three,four,five',',')
    
  2. De acordo com a resposta de Paul White, use umSEQUENCE :

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

Sequências são objetos persistentes interessantes; você pode definir o tipo de dados, o valor mínimo e o máximo, o intervalo e se ele envolve o início:

    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. De acordo com a resposta de Joseph Biju, você pode usar a IDENTITY() função (que não é a mesma que a IDENTITY propriedade em conjunto com um INSERT:

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

Observe que os dois últimos parâmetros em IDENTITY(INT,1,1)são opcionais e, por padrão, serão 1 se excluídos.

BradC
fonte
o problema é que STRING_SPLIT não garante nenhum pedido de devolução. Você pode pensar que ele sempre retornará o conjunto de linhas na ordem dos tokens na string original. Na verdade, pode até fazer isso! No entanto, não há garantia nos documentos. tudo bem se você não se importa com o pedido. Mas se você fizer (por exemplo, analisar uma linha no formato CSV), há um problema.
usar o seguinte comando
11
@ user1443098 Eu finalmente concordo com você no contexto de recomendar código para fins comerciais, como podemos ver no dba.SE. Mas para desafios no PPCG, meus padrões são um pouco diferentes; se, ao testar, meu código retornar linhas na ordem que desejo, salvarei os bytes onde puder. Semelhante à maneira como deixarei de fora e ORDER BYse puder me safar (veja minha resposta a Toasty, Burnt, Brulee , por exemplo).
21318 BradC
1

Acabei de descobrir que você pode usar números para um único caractere REPLACEpara eliminar aspas :

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

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

Isto é porque REPLACE uma conversão implícita em string.

Ambos produzem a mesma saída:

Baby Shark doo doo doo doo doo doo
BradC
fonte
0

_ e # são aliases válidos. Eu os uso com o CROSS APPLY para fazer com que apareçam as colunas retornadas que fazem parte da cláusula FROM, por exemplo

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

Eu gosto disso quando o único objetivo do CROSS APPLY é calcular uma expressão.

Nesse caso, usar o APPLY para calcular subexpressões é uma maneira interessante de tornar seu código mais seco (e mais curto). Pelo que vi nos planos de execução, não há custo adicional para essa abordagem. O compilador descobre que você está apenas computando algo e o trata como qualquer outra expressão.

user1443098
fonte
Acho cruz aplicam-se a longo prazo, é realmente difícil encontrar uma situação útil usando cruz aplicar sem encontrar outro método mais curto
t-clausen.dk
OK - encurte o exemplo dado acima!
user1443098
SELECT TOP 10 número, número * 2 n2 FROM master.dbo.spt_values ​​v
t-clausen.dk
Quero dizer, mantendo a união. A propósito, depois de criar consultas xml, o CROSS APPLY pode se tornar a única maneira de fazer isso, pois pode não haver colunas em uma subconsulta para fazer uma junção.
user1443098
Subselect é mais curto do que cruz aplicar: SELECT TOP 10 * DE (número escolha dos n, número * 2n2 DE master..spt_values) x
t-clausen.dk