T-SQL에서의 골프 팁


16

T-SQL에서 골프를 치기위한 일반적인 팁은 무엇입니까? 나는 적어도 T-SQL에 특정한 코드 골프 문제에 적용될 수있는 아이디어를 찾고 있습니다. 답변 당 하나의 팁을 게시하십시오.

원래 아이디어에 대한 Marcog에게 감사합니다. :)


팁-골프에 다른 언어를 사용하십시오. Sql 답변은 일반적으로 공감대가 거의 없거나 전혀 없습니다.
t-clausen.dk

답변:


16

내 일반적인 속임수 가방 ::

  • @ t-sql에서 유효한 변수입니다.
  • T-sql 2012 iif는 VB 스타일 사례를 추가 했습니다. 이것은 거의 항상 동등한 것보다 짧다 if else.
  • \돈 유형에서 숫자를 0으로 초기화하는 유용한 방법입니다. 을 추가하여 값을 부동 소수점으로 변환 할 수 있습니다 e. 예를 들어 4e또는 \kk를 0.00 돈으로 설정합니다.
  • rCTE100 개 미만의 숫자 표를 만드는 가장 좋은 방법 인 것 같습니다. spt_values를 사용하는 것보다 짧습니다. 100 개 이상이 필요한 경우 교차 결합하여 추가하십시오.
  • += 다른 복합 연산자는 2008 년에 추가되었습니다.이 연산자를 사용하면 몇 문자를 절약 할 수 있습니다.
  • 리터럴은 일반적으로 앨리어싱 목적으로 사용하기에 충분한 분리 문자입니다. 공백이나을 거의 필요로하지 않습니다 ;.
  • 필요한 경우 ANSI SQL 조인을 사용하십시오. Select*from A,B where condition보다 짧다select*from A join b on condition
  • while 루프가 첫 번째 반복을 수행한다고 확신 할 수 있으면 do-while 스타일 goto루프 로 다시 작성하는 것이 가장 좋습니다 .
  • 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 바이트가 추가로 소요됩니다. 이러한 종류의 논리는 정리할 수없는 많은 코드로 작업하지 않거나 문제가 압축 기반 인 경우가 아니면 효과적이지 않습니다.

여기에 예가 있습니다

도전 과제는 2, 3 및 5의 마지막 10 배수를 n으로 만드는 것입니다. 이 ( 343 bytes golfed )가 내가 생각해 낼 수있는 최고의 솔루션 이라고 가정 해 봅시다 .

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()and과 단일 열을 사용 하는 대신 바이트 수를 절약 할 수있는 것으로 확인되었습니다 SUBSTRING(). 8 개 이상인 경우 추가 따옴표와 쉼표를 피하는 것이 좋습니다.
BradC

실제로 4 개 이하의 교체 제품의 경우 구식으로 바이트를 절약 할 수 있습니다.SET @=REPLACE(REPLACE(REPLACE(...
BradC

4

재미있는 것이 있습니다. 이것은 열의 값을 단일 튜플로 변환합니다.

편집 : 의견 주셔서 감사합니다. 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,...있습니다. 그러나 실제로는 XML 트릭보다 9 자 더 깁니다. (
Jacob

1
더 짧게 만들 수 있습니다. Ltrimselect (xml path ( '')의 경우 select ...)가을 반환하므로 필요하지 않습니다 nvarchar(max). 또한 열을 해결하려면 비 돌연변이 식을 사용하십시오. 숫자의 v+0경우 문자열에 빈 문자열 등을 추가 할 수 있습니다 .이 골프 팁을 실제로 고려하지는 않지만 SQL 서버에서 쿼리를 작성하는 방법은 슬프게도 현실입니다.
Michael B

3

T-SQL에서 비트 연산자 를 사용할 수 있습니다 .

구체적인 예는 없지만 T-SQL에서 골프를 타면 알 수있는 사실이라고 생각합니다.


1
이것은 매우 유효합니다. 와 같은 조건을 작성하는 대신 x=0 or y=0논리적으로 동등한 x|y=0것으로 작성하면 꽤 많은 바이트를 절약 할 수 있습니다 !
Michael B


3

과학적 표기법은 select 1000000000= select 1E9select 0.000001= 와 같이 매우 크고 작은 숫자를 표현하는 더 짧은 방법 select 1E-6입니다.


2

Michael B는 숫자 테이블에 재귀 적 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

이 마지막 것이 숫자 순서로 반환되지는 않지만 ORDER BY 1


2

매우 긴 문자열에는 GZIP 압축을 사용하십시오!

따라서 SQL 2016은 COMPRESS함수 (및 DECOMPRESS함수)를 추가 하여 문자열 또는 이진을 GZIP 할 수있는 기능을 추가했습니다.

문제는 골프를 위해 이것을 이용하는 방법을 즉시 알 수 없다는 것입니다. COMPRESS는 문자열을 사용할 수 있지만 바이트를VARBINARY 짧게 (SQL 필드에 저장 한 경우 ) 짧지 만 문자 가 더 긴 (16 진수)을 반환합니다 .VARBINARY

나는 전에 이것을 가지고 놀았지만 마침내 SO 에 대한 이 오래된 대답을 기반으로 작동하는 버전을 만들 수있었습니다 . 이 게시물은 새로운 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.

편집 : 압축 해제 코드의 짧은 버전, @digscoop 제공 :

다음을 CAST사용하여 외부 를 암시 적 변환 으로 변경하여 10 바이트를 절약하십시오 CONCAT.

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

XML대신 대신 유형의 변수를 선언 VARCHAR(MAX)하고 inner에 저장할 수 있습니다 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 개 이하의 행으로 짧아지고 하단 버전 (왼쪽 및 SUBSTRING으로 인해)이 8 개 이상의 행으로 짧아집니다 . 정확한 데이터에 따라 마일리지가 다를 수 있습니다.

5 : 매우 긴 텍스트 시퀀스에 REPLACE 및 EXEC 사용

편안하게 drei의 탁월한 대답의 맥락에서 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의 훌륭한 답변 here 에서 영감을 얻어 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 Data Explorer (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

번역 ( SQL 2017 이상 )

TRANSLATE여러 개의 중첩 된 REPLACE명령문이 아니라 한 번에 여러 문자를 바꿀 수 있습니다 . 그러나 너무 축하하지 말고 개별 단일 문자 만 다른 단일 문자로 바꿉니다.

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

두 번째 문자열의 각 문자는 세 번째 문자열의 해당 문자 로 바뀝니다 .

우리는 다음과 같은 것으로 많은 캐릭터를 제거 할 수있는 것처럼 보입니다. REPLACE(TRANSLATE('source string','ABCD','XXXX'),'X','')


뿐만 아니라, 같은 일부 더 흥미로운 것들 CONCAT_WSSTRING_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

Paul의 위와 같은 질문에서 Anuj Tripathi는 다음과 같은 트릭을 사용했습니다 .

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

또는 의견에서 pinkfloydx33이 제안한대로 :

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

이것은 모든 실제 SQL 내용 에 의존하지 않으며 systypes시스템 뷰가 존재하고 (모든 MS SQL 데이터베이스에 있음) 최소 10 개의 행 (최신 버전의 SQL의 경우 34를 포함하는 것으로 보입니다) ). 이름이 짧은 시스템 sys.접두사를 찾을 수 없으므로 ( 접두사가 필요하지 않음 ) 이상적입니다.


1

STRING_SPLIT 결과에 숫자 열을 추가하는 데 대한 흥미로운 아이디어는 dba.stackexchange에서이 질문을 참조하십시오 .

같은 문자열이 주어지면 'one,two,three,four,five'다음과 같은 것을 얻고 싶습니다.

value   n
------ ---
one     1
two     2
three   3
four    4
five    5
  1. Joe Obbish의 답변, 사용 ROW_NUMBER()및 순서 NULL또는 상수 :

    SELECT value, ROW_NUMBER() OVER(ORDER BY (SELECT 1))n
    FROM STRING_SPLIT('one,two,three,four,five',',')
    
  2. Paul White의 답변에 따라SEQUENCE :

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

시퀀스는 흥미로운 영구 객체입니다. 데이터 유형, 최소값 및 최대 값, 간격 및 시작 부분을 둘러 쌀지 여부를 정의 할 수 있습니다.

    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. 비주 호세의 대답은 당, 당신이 사용할 수있는 기능 입니다 ( 하지 와 같은 특성 은 INSERT와 함께를 :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 형식으로 행 구문 분석) 문제가 있습니다.
user1443098

1
@ user1443098 dba.SE에서 볼 수 있듯이 비즈니스 목적으로 코드를 추천하는 맥락에서 궁극적으로 귀하에게 동의합니다. 그러나 PPCG에 대한 도전의 경우 제 표준은 약간 다릅니다. 테스트에서 코드가 원하는 순서대로 행을 반환하면 가능한 한 바이트를 저장합니다. ORDER BY내가 도망 갈 수 있는 방법과 비슷한 방법과 비슷 합니다 ( 예 : Toasty, Burnt, Brulee 에 대한 답변 참조 ).
BradC

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

OK-위에서 주어진 예를 줄이십시오!
user1443098

상위 10 개 번호 선택, 숫자 * 2 n2 FROM master.dbo.spt_values ​​v
t-clausen.dk

조인 유지. 그런데 XML 쿼리를 작성하면 하위 쿼리에 열이 조인을 수행 할 수 없으므로 CROSS APPLY가이를 수행 할 수있는 유일한 방법이 될 수 있습니다.
user1443098

하위 선택이 교차 적용보다 짧습니다. SELECT top 10 * FROM (SELECT number n, number * 2n2 FROM master..spt_values) x
t-clausen.dk
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.