Consejos para jugar golf en T-SQL

16

¿Qué consejos generales tienes para jugar al golf en T-SQL? Estoy buscando ideas que se puedan aplicar a los problemas de golf de código en general que sean al menos algo específicos para T-SQL. Por favor, publique un consejo por respuesta.

Gracias a Marcog por la idea original. :)

Michael B
fuente
Un consejo: use un idioma diferente para jugar al golf. Las respuestas SQL generalmente reciben muy pocos o ningún voto positivo.
t-clausen.dk

Respuestas:

16

Mi bolsa general de trucos ::

  • @ es una variable válida en t-sql.
  • T-sql 2012 agregó iifuna declaración de caso de estilo VB. Esto es casi siempre más corto que un equivalente if else.
  • \es una forma útil de inicializar un número como 0 en un tipo de dinero. Puede convertir un valor en un flotante agregando e. por ejemplo, 4eo \kque establecerá k en el valor 0.00 dinero.
  • rCTEparece ser la mejor manera de crear una tabla de números de menos de 100 entradas. Incluso más corto que usar spt_values. Si necesita más de un 100, cruce y agregue.
  • += y otros operadores compuestos se agregaron en 2008. Úselos para guardar algunos caracteres.
  • Los literales suelen ser un delimitador suficientemente bueno para fines de alias. Raramente necesitas un espacio o un ;.
  • Utilice las uniones ANSI SQL si las necesita. Select*from A,B where conditiones más corto queselect*from A join b on condition
  • Si puede estar seguro de que su bucle while hará la primera iteración, es mejor reescribirlo como un gotobucle de estilo do- while.
  • STR()es la función más corta para convertir un int en una cadena. Si está realizando más de una conversión o puede necesitar concatenar numerosos tipos de datos diferentes, considere la concatfunción. Por ejemplo, 'hello'+str(@)es más corto que concat('hello',@), pero hello+str(@)+str(@a)es más largo queconcat('hello',@,@a)

Por ejemplo, estos dos son semánticamente equivalentes.

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

Puede usar Valuespara crear una tabla o subconsulta. Esto solo será realmente un beneficio si necesita algunas filas constantes.

Michael B
fuente
Para mí, $ es un poco más obvio que \ para inicializar un número como 0 en un tipo de dinero. YMMV
user1443098
5

Compresión de código usando SQL

SQL es prolijo, tiene puntajes altos y, por mucho que los amemos, SELECT FROM WHEREcuesta 23 bytes con cada uso. Puede comprimir estas y otras palabras repetidas o fragmentos de código completos. ¡Hacer esto disminuirá el costo marginal del código repetido a 1 byte! *

Cómo funciona esto:

  • Se declara una variable y se le asigna un código SQL comprimido
  • Una tabla modifica la variable. Cada fila desinfla la variable.
  • La variable modificada se ejecuta.

El problema:

El costo inicial es cercano a 100 bytes y cada fila en la tabla de reemplazo cuesta otros 6 bytes. Este tipo de lógica no será muy efectiva a menos que esté trabajando con un montón de código que no puede recortar o que el desafío esté basado en la compresión.

Aquí hay un ejemplo

El desafío es obtener los últimos 10 múltiplos de 2,3 y 5 que conducen a n. Digamos que esto ( 343 bytes golfed ) es la mejor solución que se me ocurrió:

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

Ejemplo después de comprimir el código

Esto ejecuta el mismo código que el anterior, tiene ~ 302 bytes de golf .

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)
cómodamentedrei
fuente
Gran estrategia, ese estilo de reemplazo múltiple también puede ser útil en escenarios más convencionales.
BradC
1
Después de algunas pruebas, he determinado que si su lista de reemplazos tiene 7 o menos elementos, guardaría bytes haciendo en SELECT @=REPLACE(@,i,j)FROM(VALUES(...)x(i,j)lugar de usar una sola columna con LEFT()y SUBSTRING(). Si tiene 8 o más, entonces evitar las comillas y comillas adicionales es una buena compensación.
BradC
En realidad, para 4 o menos reemplazos, ahorraría bytes con un anticuadoSET @=REPLACE(REPLACE(REPLACE(...
BradC
4

Aquí hay uno divertido. Esto convertirá los valores en una columna en una sola tupla.

EDITAR: Gracias por los comentarios. Parece que la forma más corta de enrollar sin las etiquetas XML es:

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

Nota: si XML es una salida válida, puede omitir la selección externa y los parens. Además column1+'', solo funciona para cadenas. Para los tipos de números, es mejor hacerlocolumn1+0

cómodamentedrei
fuente
1
En realidad volverá <column_name>value1</column_name><column_name>value2</column_name>.... Para tener un CSV de una columna, puede DECLARE @ VARCHAR(MAX)='';SELECT @+=column_name+',' FROM table_name;SELECT @(gracias por el primer consejo de @ MichaelB) que volverá value1,value2,.... Sin embargo, en realidad es 9 caracteres más largo que tu truco XML :(
Jacob
1
Tenga en cuenta que puede hacer esto más corto. Ltrimno es necesario ya que select (select ... for xml path ('')) devuelve un nvarchar(max). Además, para resolver el asunto de la columna, simplemente use una expresión no mutante. Para los números que puede hacer v+0, para la cadena agregue una cadena vacía, etc. Aunque realmente no considero que esto sea un consejo de golf, es una triste realidad de cómo escribir consultas en el servidor SQL.
Michael B
3

Es posible usar algunos operadores bit a bit en T-SQL .

No tengo un ejemplo concreto, pero creo que es bueno saberlo cuando se juega golf en T-SQL.

Jacob
fuente
1
Esto es muy valido. ¡En lugar de escribir una condición como x=0 or y=0, puede escribir eso como el equivalente lógico x|y=0que ahorra bastantes bytes!
Michael B
3

Imprimir en lugar de Seleccionar

¡Es tan simple como eso! Así que aquí hay un políglota T-SQL / Python:

print'Hello, World!'

Pruébalo en línea

mbomb007
fuente
3

La notación científica es un método más corto para expresar números muy grandes y muy pequeños, por ejemplo, select 1000000000= select 1E9y select 0.000001= select 1E-6.

naXa
fuente
2

Michael B mencionó el uso de un CTE recursivo para una tabla numérica , pero no mostró un ejemplo. Aquí hay una versión de MS-SQL que elaboramos en este otro hilo :

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

Tenga en cuenta que puede cambiar el valor inicial ( 1 n), el intervalo ( n + 1) y el valor final ( n < 99).

Sin embargo, si necesita más de 100 filas, deberá agregar option (maxrecursion 0):

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

o unirse a la rCTE a sí mismo:

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

Aunque no se garantiza que este último regrese en orden numérico sin un ORDER BY 1

BradC
fuente
2

Utilice la compresión GZIP para cadenas muy largas.

Entonces sabía que SQL 2016 agregó una COMPRESSfunción (y una DECOMPRESSfunción), que (finalmente) brinda la capacidad de GZIP una cadena o binario.

El problema es que no está claro de inmediato cómo aprovechar esto para jugar al golf; COMPRESSpuede tomar una cadena pero devuelve un VARBINARY, que es más corto en bytes (cuando se almacena en un VARBINARYcampo SQL ), pero es más largo en caracteres (hexadecimal).

He jugado con esto antes, pero finalmente pude armar una versión funcional, basada en esta vieja respuesta en SO . Esa publicación no usa las nuevas funciones GZIP, pero convierte una VARBINARYcadena codificada en Base-64. Solo necesitábamos insertar las nuevas funciones en el lugar correcto y desarrollarlas un poco.

Aquí está el código que puede usar para convertir su cadena muy larga a la cadena comprimida codificada 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))

Tome la salida y úsela en su código en lugar de la cadena larga original, junto con:

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

Entonces, en lugar de su 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.'

tendrías esto ( 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))

Vea esta respuesta que me ahorró casi 200 bytes.

No he hecho los cálculos, pero claramente debido a la sobrecarga, esto solo será efectivo para cadenas extremadamente largas. Probablemente hay otros lugares que no se pueden usar; Ya descubrí que tienes que SELECThacerlo, no puedes PRINT, de lo contrario obtienes:

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

EDITAR : versión más corta del código de descompresión, cortesía de @digscoop :

Ahorre 10 bytes cambiando el exterior CASTa una conversión implícita usando CONCAT:

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

También puede declarar una variable de tipo en XMLlugar de VARCHAR(MAX)y guardar en el interior CAST:

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

Esto es un poco más largo por sí solo, pero si lo necesita en una variable por otros motivos, entonces podría ayudar.

BradC
fuente
Bien, no conozco SQL, pero todavía se ve genial
MilkyWay90
1

Algunas reflexiones sobre la creación y el uso de tablas para desafíos:

1. La entrada SQL se puede tomar a través de una tabla preexistente

Métodos de entrada / salida de golf de código :

Los SQL pueden recibir información de una tabla con nombre

Crear y completar esta tabla con valores de entrada no cuenta para el total de bytes, solo puede suponer que ya está allí.

Esto significa que sus cálculos pueden salir a través de SELECT simple desde la tabla de entrada:

SELECT 2*SQRT(a)FROM t

2. Si es posible, en realidad no cree una tabla

En lugar de (69 bytes):

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

Solo haz (43 bytes):

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

3. Si es posible, cree la tabla con un SELECCIONAR EN

En lugar de (39 bytes):

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

Haga esto (17 bytes):

SELECT 2 p INTO t

4: Considere mezclar varias columnas juntas

Aquí hay dos variaciones que devuelven el mismo resultado:

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)

Después de algunas pruebas, la versión superior (columnas múltiples) parece más corta con 7 o menos filas , la versión inferior (debido a la IZQUIERDA y SUBSTRING) es más corta con 8 o más filas . Su kilometraje puede variar, dependiendo de sus datos exactos.

5: Use REPLACE y EXEC para secuencias de texto muy largas

En la línea de la excelente respuesta de cómodamentedrei , si tiene 15 o más valores , use REPLACEun símbolo para deshacerse de los '),('separadores repetidos entre 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(@)

Si usted está ya utilizando SQL dinámico por otras razones (o tener múltiples sustituye), entonces el umbral en el que esto vale la pena es mucho menor.

6: Use un SELECT con columnas con nombre en lugar de un montón de variables

Inspirado por la excelente respuesta de jmlt aquí , reutilice las cadenas a través de un SELECCIONAR:

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

devoluciones

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

(Para MS SQL, cambié \ta un retorno en línea y cambié CONCAT()a +para guardar bytes).

BradC
fuente
1

Etiquete su código para resaltar la sintaxis de T-SQL

En lugar de solo:

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

Incluya una etiqueta de idioma como esta:

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

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

y el resultado será:

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

Aproveche las nuevas características / funciones en MS SQL 2016 y SQL 2017

Si no tiene copias locales para trabajar, puede jugar en línea con el Explorador de datos de StackExchange (SQL 2016) o con dbfiddle.uk (SQL 2016 o SQL "vNext").

STRING_SPLIT ( SQL 2016 y posterior )

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

Si necesita alias de la tabla o hacer referencia al nombre de la columna:

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

TRIM ( SQL 2017 o posterior )

Más corto que RTRIM()y ciertamente más corto que LTRIM(RTRIM()).

También tiene una opción para eliminar otros caracteres o conjuntos de caracteres desde el principio o el final:

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

devoluciones L Server 2

TRADUCIR ( SQL 2017 o posterior )

TRANSLATEle permite reemplazar varios caracteres en un solo paso, en lugar de un conjunto de REPLACEdeclaraciones anidadas . Pero no celebre demasiado , solo reemplaza caracteres individuales individuales con caracteres individuales diferentes.

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

Cada carácter en la segunda cadena se reemplaza por el carácter correspondiente en la tercera cadena.

Parece que podríamos eliminar un montón de personajes con algo como REPLACE(TRANSLATE('source string','ABCD','XXXX'),'X','')


Algunos más interesantes también, como CONCAT_WSy STRING_AGGque probablemente valen la pena también.

BradC
fuente
1

Santa vaca, he descubierto la maravilla de PARSENAME( SQL 2012 o superior ).

La función se creó para aislar las partes de un nombre de objeto como servername.dbname.dbo.tablename, pero funciona para cualquier valor separado por puntos. Solo recuerda que cuenta desde la derecha , no desde la izquierda:

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

Si tiene menos de 4 valores separados por puntos, devolverá NULLel resto (pero aún cuenta de derecha a izquierda ):

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

Sin embargo, aquí es donde entra la magia: ¡combínelo con STRING_SPLIT(2016 o superior) para hacer tablas en varias columnas en memoria!

Viejo y roto:

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

Nuevo calor:

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, sus ahorros reales dependen del tamaño y el contenido de la tabla, y de cómo lo está utilizando exactamente.

Tenga en cuenta que si sus campos son de ancho constante, probablemente sea mejor usarlos LEFTy RIGHTsepararlos en lugar de PARSENAME(no solo porque los nombres de las funciones son más cortos, sino también porque puede eliminar los separadores por completo).

BradC
fuente
No estoy seguro de cuándo salió PARSENAME, pero hay artículos que lo describen desde 2003
t-clausen.dk
1

Un par de trucos más no relacionados que vi y quise preservar:

  1. Use GO #para repetir un bloque un número específico de veces .

Vi este ingenioso truco en la excelente respuesta de Paul .

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

Esto, por supuesto, restablecería cualquier variable de contador en el bloque, por lo que tendría que comparar esto con un WHILEbucle o un x: ... GOTO xbucle.

  1. SELECT TOP ... FROM systypes

De la misma pregunta que la anterior de Pablo, Anuj Tripathi usó el siguiente truco :

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

o, como lo sugiere pinkfloydx33 en los comentarios:

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

Tenga en cuenta que esto no se basa en ninguno de los contenidos reales de systypes, solo que la vista del sistema existe (que existe en todas las bases de datos MS SQL) y contiene al menos 10 filas (parece contener 34, para las versiones más recientes de SQL ) No pude encontrar ninguna vista del sistema con nombres más cortos (que no requirieran un sys.prefijo), por lo que esto puede ser ideal.

BradC
fuente
1

Ver esta pregunta en dba.stackexchange para obtener algunas ideas interesantes para agregar una columna numérica a un resultado de STRING_SPLIT.

Dada una cadena como 'one,two,three,four,five', queremos obtener algo como:

value   n
------ ---
one     1
two     2
three   3
four    4
five    5
  1. Según la respuesta de Joe Obbish, use ROW_NUMBER()y ordene por NULLo una constante:

    SELECT value, ROW_NUMBER() OVER(ORDER BY (SELECT 1))n
    FROM STRING_SPLIT('one,two,three,four,five',',')
    
  2. Según la respuesta de Paul White, use unSEQUENCE :

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

Las secuencias son interesantes objetos persistentes; puede definir el tipo de datos, el valor mínimo y máximo, el intervalo y si se ajusta al principio:

    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. Según la respuesta de Biju jose, puede usar la IDENTITY() función (que no es lo mismo que la IDENTITY propiedad junto con un INSERT:

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

Tenga en cuenta que los dos últimos parámetros en IDENTITY(INT,1,1)son opcionales y su valor predeterminado será 1 si se excluye.

BradC
fuente
El problema es que STRING_SPLIT no garantiza ningún pedido de devolución. Puede pensar que siempre devolverá el conjunto de filas en el orden de los tokens en la cadena original. De hecho, ¡incluso puede hacer eso! Sin embargo, no hay garantía en los documentos. está bien si no te importa el pedido. Pero si lo hace (por ejemplo, analizar una fila en formato CSV), hay un problema.
user1443098
1
@ user1443098 Finalmente estoy de acuerdo con usted en el contexto de recomendar el código para un propósito comercial, como podríamos ver en dba.SE. Pero para los desafíos en PPCG, mis estándares son un poco diferentes; si al probar mi código devuelve filas en el orden que quiero, guardaré los bytes donde pueda. Similar a cómo dejaré de lado y ORDER BYsi puedo salirse con la suya (vea mi respuesta a Toasty, Burnt, Brulee , por ejemplo).
BradC
1

Acabo de descubrir que puedes usar números para un solo carácter REPLACEpara eliminar comillas :

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

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

Esto es porque REPLACE hace una conversión implícita a cadena.

Ambos producen la misma salida:

Baby Shark doo doo doo doo doo doo
BradC
fuente
0

_ y # son alias válidos. Los uso con CROSS APPLY para que parezca que las columnas que devuelve son parte de la cláusula FROM, por ejemplo

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

Me gusta cuando el único propósito de CROSS APPLY es calcular una expresión.

Para el caso, usar APPLY para calcular subexpresiones es una buena manera de hacer que su código sea SECO (y más corto). Por lo que he visto en los planes de ejecución, este enfoque no tiene un costo adicional. El compilador se da cuenta de que solo estás calculando algo y lo trata como cualquier otra expresión.

usuario1443098
fuente
Creo que la aplicación cruzada es demasiado larga, es realmente difícil encontrar una situación útil usando la aplicación cruzada sin encontrar otro método más corto
t-clausen.dk
OK - acortar el ejemplo dado arriba!
user1443098
SELECCIONE el número TOP 10, número * 2 n2 DESDE master.dbo.spt_values ​​v
t-clausen.dk
Quiero decir, mantener la unión. Por cierto, una vez que crea consultas xml, CROSS APPLY puede convertirse en la única forma de hacerlo, ya que puede que no haya columnas en una subconsulta, haga una unión.
user1443098
La subselección es más corta que la aplicación cruzada: SELECCIONE los 10 mejores * DESDE (SELECCIONE el número n, el número * 2n2 DESDE los valores maestros..spt_) x
t-clausen.dk