Mẹo chơi gôn trong T-SQL


16

Bạn có mẹo chung nào để chơi golf trong T-SQL? Tôi đang tìm kiếm những ý tưởng có thể được áp dụng cho các vấn đề về mã golf nói chung ít nhất là cụ thể đối với T-SQL. Xin vui lòng gửi một lời khuyên cho mỗi câu trả lời.

Cảm ơn Marcog cho ý tưởng ban đầu. :)


một mẹo - sử dụng một ngôn ngữ khác để chơi gôn. Câu trả lời Sql thường nhận được rất ít hoặc không có upvote nào cả.
t-clausen.dk

Câu trả lời:


16

Túi thủ đoạn chung của tôi ::

  • @ là một biến hợp lệ trong t-sql.
  • T-sql 2012 đã thêm iifmột tuyên bố trường hợp phong cách VB. Điều này hầu như luôn luôn ngắn hơn một tương đương if else.
  • \là một cách hữu ích để khởi tạo một số là 0 trong một loại tiền. Bạn có thể chuyển đổi một giá trị thành float bằng cách thêm e. ví dụ 4ehoặc \ksẽ đặt k thành giá trị 0,00 tiền.
  • rCTEdường như là cách tốt nhất để tạo một bảng số ít hơn 100 mục. Thậm chí ngắn hơn so với sử dụng spt_values. Nếu bạn cần nhiều hơn 100, tham gia chéo và thêm chúng.
  • += và các toán tử ghép khác đã được thêm vào năm 2008. Sử dụng chúng, nó sẽ lưu một vài ký tự.
  • Văn học thường là một dấu phân cách đủ tốt cho mục đích răng cưa. Bạn hiếm khi cần một không gian hoặc a ;.
  • Sử dụng ANSI SQL tham gia nếu bạn cần chúng. Select*from A,B where conditionngắn hơnselect*from A join b on condition
  • Nếu bạn có thể yên tâm rằng vòng lặp while của bạn sẽ thực hiện lần lặp đầu tiên, tốt nhất bạn nên viết lại nó như một gotovòng lặp kiểu do- while.
  • STR()là hàm ngắn nhất để biến int thành một chuỗi. Nếu bạn đang thực hiện nhiều chuyển đổi hoặc có thể cần ghép nhiều kiểu dữ liệu khác nhau, hãy xem xét concathàm. Ví dụ: 'hello'+str(@)ngắn hơn concat('hello',@), nhưng hello+str(@)+str(@a)dài hơnconcat('hello',@,@a)

Ví dụ Hai cái này tương đương về mặt ngữ nghĩa.

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

Bạn có thể sử dụng Valuesđể tạo một bảng hoặc truy vấn con. Điều này sẽ chỉ thực sự là một lợi ích nếu bạn cần một vài hàng không đổi.


Đối với tôi, $ rõ ràng hơn một chút so với \ để khởi tạo một số là 0 trong một loại tiền. YMMV
dùng1443098

5

Nén mã bằng SQL

SQL dài dòng, điểm số cao và nhiều như chúng ta yêu thích, SELECT FROM WHEREchi phí 23 byte cho mỗi lần sử dụng. Bạn có thể nén những từ này và các từ lặp lại khác hoặc toàn bộ đoạn mã. Làm điều này sẽ giảm chi phí cận biên của mã lặp lại xuống 1 byte! *

Cách thức hoạt động:

  • Một biến được khai báo và gán mã SQL nén
  • Một bảng sửa đổi các biến. Mỗi hàng xì hơi biến.
  • Biến được sửa đổi được thực thi.

Vấn đề:

Chi phí trả trước gần 100 byte và mỗi hàng trong bảng thay thế tốn thêm 6 byte. Kiểu logic này sẽ không hiệu quả trừ khi bạn làm việc với rất nhiều mã mà bạn không thể cắt giảm hoặc thách thức là dựa trên nén.

Đây là một ví dụ

Thách thức là có được 10 bội số cuối cùng của 2,3 và 5 dẫn đến n. Giả sử điều này ( 343 byte được đánh gôn ) là giải pháp tốt nhất tôi có thể đưa ra:

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

Ví dụ sau khi mã được nén

Điều này thực thi cùng một mã như trên, là ~ 302 byte được đánh gôn .

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)

Chiến lược tuyệt vời, phong cách đa thay thế cũng có thể hữu ích trong các tình huống thông thường hơn.
BradC

1
Sau một số thử nghiệm, tôi đã xác định rằng nếu danh sách thay thế của bạn có 7 mục trở xuống , bạn sẽ lưu byte bằng cách thực hiện SELECT @=REPLACE(@,i,j)FROM(VALUES(...)x(i,j)thay vì sử dụng một cột duy nhất với LEFT()SUBSTRING(). Nếu bạn có 8 hoặc nhiều hơn, thì việc tránh các trích dẫn thêm và dấu phẩy là một sự đánh đổi tốt.
BradC

Trên thực tế với 4 lần thay thế hoặc ít hơn, bạn sẽ lưu byte với kiểu cũSET @=REPLACE(REPLACE(REPLACE(...
BradC

4

Đây là một trong những buồn cười. Điều này sẽ chuyển đổi các giá trị trong một cột thành một tuple duy nhất.

EDIT: Cảm ơn bạn đã cho ý kiến. Có vẻ như cách ngắn nhất để cuộn lên mà không có các thẻ XML là:

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

Lưu ý: nếu XML là đầu ra hợp lệ, bạn có thể bỏ qua lựa chọn bên ngoài và parens. Ngoài ra column1+'', chỉ hoạt động cho chuỗi. Đối với các loại số, tốt nhất nên làmcolumn1+0


1
Thật ra nó sẽ trở lại <column_name>value1</column_name><column_name>value2</column_name>.... Để có CSV từ một cột, bạn có thể DECLARE @ VARCHAR(MAX)='';SELECT @+=column_name+',' FROM table_name;SELECT @(cảm ơn vì mẹo đầu tiên của @ MichaelB) sẽ trả lại value1,value2,.... Tuy nhiên, nó thực sự dài hơn 9 ký tự so với thủ thuật XML của bạn :(
Jacob

1
Lưu ý bạn có thể làm điều này ngắn hơn. Ltrimkhông cần thiết vì select (select ... cho đường dẫn xml ('')) trả về một nvarchar(max). Ngoài ra, để giải quyết điều cột, chỉ cần sử dụng một biểu thức không đột biến. Đối với các số bạn có thể làm v+0, đối với chuỗi thêm chuỗi trống, v.v. Mặc dù tôi không thực sự coi đây là một mẹo chơi gôn, nhưng thật đáng buồn là thực tế về cách viết truy vấn trong máy chủ sql.
Michael B

3

Có thể sử dụng một số toán tử bitwise trong T-SQL .

Tôi không có một ví dụ cụ thể, nhưng tôi tin rằng đó là một thực tế cần biết khi chơi golf trong T-SQL.


1
Điều này rất hợp lệ. Thay vì viết một điều kiện như thế x=0 or y=0, bạn có thể viết nó dưới dạng tương đương logic x|y=0giúp tiết kiệm khá nhiều byte!
Michael B


3

Ký hiệu khoa học là một phương pháp ngắn hơn để thể hiện các số rất lớn và rất nhỏ, ví dụ select 1000000000= select 1E9select 0.000001= select 1E-6.


2

Michael B đã đề cập đến việc sử dụng CTE đệ quy cho bảng số , nhưng không hiển thị một ví dụ. Đây là phiên bản MS-SQL mà chúng tôi đã thực hiện trong chuỗi khác này :

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

Lưu ý rằng bạn có thể thay đổi giá trị bắt đầu ( 1 n), khoảng ( n + 1) và giá trị kết thúc ( n < 99).

Tuy nhiên, nếu bạn cần nhiều hơn 100 hàng, bạn sẽ cần thêm option (maxrecursion 0):

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

hoặc tham gia rCTE với chính nó:

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

Mặc dù cái cuối cùng này không được đảm bảo để trả về theo thứ tự số mà không có ORDER BY 1


2

Sử dụng nén GZIP cho các chuỗi rất dài!

Vì vậy, tôi biết rằng SQL 2016 đã thêm một COMPRESShàm (và một DECOMPRESShàm), mà (cuối cùng) mang lại khả năng cho GZIP một chuỗi hoặc nhị phân.

Vấn đề là không rõ ràng làm thế nào để tận dụng lợi thế này để chơi gôn; COMPRESScó thể lấy một chuỗi nhưng trả về a VARBINARY, ngắn hơn bằng byte (khi được lưu trữ trong VARBINARYtrường SQL ), nhưng dài hơn bằng ký tự (hex thô).

Tôi đã từng chơi với nó trước đây, nhưng cuối cùng tôi đã có thể kết hợp một phiên bản hoạt động, dựa trên câu trả lời cũ này trên SO . Bài đăng đó không sử dụng các chức năng GZIP mới, nhưng nó chuyển đổi mộtVARBINARY chuỗi được mã hóa Base-64. Chúng ta chỉ cần chèn các chức năng mới vào đúng chỗ, và đánh gôn lên một chút.

Đây là mã bạn có thể sử dụng để chuyển đổi chuỗi rất dài của mình thành chuỗi nén được mã hóa 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))

Lấy đầu ra và sử dụng nó trong mã của bạn thay cho chuỗi dài ban đầu, cùng với:

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

Vì vậy, thay vì mã gốc của bạn ( 1471 byte )

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

bạn sẽ có cái này ( 1034 byte ):

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

Xem câu trả lời này này đã tiết kiệm cho tôi gần 200 byte.

Tôi đã không làm toán, nhưng rõ ràng do chi phí quá cao, điều này sẽ chỉ có hiệu quả đối với các chuỗi cực dài. Có lẽ có những nơi khác không thể được sử dụng; Tôi đã phát hiện ra bạn phải làm SELECTđiều đó, bạn không thể PRINT, nếu không bạn sẽ nhận được:

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

EDIT : Phiên bản ngắn hơn của mã giải nén, với sự cho phép của @digscoop :

Lưu 10 byte bằng cách thay đổi bên ngoài CASTthành một chuyển đổi ngầm định bằng cách sử dụng CONCAT:

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

Bạn cũng có thể khai báo một biến kiểu XMLthay vì VARCHAR(MAX)và lưu vào bên trong CAST:

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

Bản thân nó dài hơn một chút , nhưng nếu bạn cần nó trong một biến vì những lý do khác, thì nó có thể giúp ích.


Thật tuyệt, tôi không biết SQL nhưng điều này vẫn rất tuyệt
MilkyWay90

1

Một vài suy nghĩ về việc tạo và sử dụng các bảng cho các thách thức:

1. Đầu vào SQL có thể được thực hiện thông qua một bảng có sẵn

Phương thức nhập / xuất mã của Golf Golf :

SQL có thể lấy đầu vào từ một bảng được đặt tên

Tạo và điền vào bảng này với các giá trị đầu vào không được tính vào tổng byte của bạn, bạn có thể giả sử nó đã ở đó.

Điều này có nghĩa là các tính toán của bạn có thể xuất qua CHỌN đơn giản từ bảng đầu vào:

SELECT 2*SQRT(a)FROM t

2. Nếu có thể, đừng thực sự tạo một bảng

Thay vì (69 byte):

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

Chỉ cần làm (43 byte):

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

3. Nếu có thể, hãy tạo bảng với CHỌN VÀO

Thay vì (39 byte):

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

Làm điều này (17 byte):

SELECT 2 p INTO t

4: Xem xét việc trộn nhiều cột với nhau

Đây là hai biến thể trả về cùng một đầu ra:

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)

Sau một số thử nghiệm, phiên bản trên cùng (nhiều cột) có vẻ ngắn hơn với 7 hàng hoặc ít hơn , phiên bản dưới cùng (do TRÁI và BẮT ĐẦU) ngắn hơn với 8 hàng trở lên . Số dặm của bạn có thể thay đổi, tùy thuộc vào dữ liệu chính xác của bạn.

5: Sử dụng REPLACE và EXEC cho các chuỗi văn bản rất dài

Trong câu trả lời xuất sắc của Comfortinglydrei , nếu bạn có 15 giá trị trở lên , hãy sử dụng REPLACEbiểu tượng để loại bỏ các '),('dấu phân cách lặp lại giữa các phần tử:

114 ký tự:

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

112 ký tự:

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

Nếu bạn đã sử dụng SQL động vì các lý do khác (hoặc có nhiều thay thế), thì ngưỡng mà giá trị này thấp hơn nhiều.

6: Sử dụng CHỌN với các cột được đặt tên thay vì một loạt các biến

Lấy cảm hứng từ câu trả lời tuyệt vời của jmlt tại đây , sử dụng lại chuỗi thông qua CHỌN:

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

trả lại

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

(Đối với MS SQL, tôi đã thay đổi thành \ttrả về nội dòng và thay đổi CONCAT()thành +để lưu byte).


1

Gắn thẻ mã của bạn để tô sáng cú pháp T-SQL

Thay vì chỉ:

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

Bao gồm một thẻ ngôn ngữ như thế này:

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

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

và kết quả sẽ là:

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

1

Tận dụng các tính năng / chức năng mới trong MS SQL 2016 và SQL 2017

Nếu bạn không có các bản sao cục bộ để làm việc, bạn có thể chơi trực tuyến với StackExchange Data Explorer (SQL 2016) hoặc với dbfiddle.uk (SQL 2016 hoặc SQL "vNext").

STRINGinksLIT ( SQL 2016 trở lên )

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

Nếu bạn cần đặt bí danh cho bảng hoặc tham khảo tên cột:

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

TRIM ( SQL 2017 trở lên )

Ngắn hơn RTRIM()và chắc chắn ngắn hơn LTRIM(RTRIM()).

Cũng có một tùy chọn để loại bỏ các ký tự hoặc bộ ký tự khác từ đầu hoặc cuối:

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

trả lại L Server 2

TRANSLATE ( SQL 2017 trở lên )

TRANSLATEcho phép bạn thay thế nhiều ký tự trong một bước, thay vì một loạt các REPLACEcâu lệnh lồng nhau . Nhưng đừng ăn mừng quá nhiều, nó chỉ thay thế các ký tự đơn lẻ bằng các ký tự đơn khác nhau.

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

Mỗi ký tự trong chuỗi thứ hai được thay thế bằng ký tự tương ứng trong chuỗi thứ 3.

Có vẻ như chúng ta có thể loại bỏ một loạt các nhân vật với một cái gì đó như REPLACE(TRANSLATE('source string','ABCD','XXXX'),'X','')


Một số người thú vị hơn là tốt, thích CONCAT_WSSTRING_AGGđó có lẽ cũng đáng xem.


1

Holy cow, tôi đã khám phá điều kỳ diệu của PARSENAME( SQL 2012 trở lên ).

Hàm được xây dựng để cô lập các phần của tên đối tượng như thế nào servername.dbname.dbo.tablename, nhưng nó hoạt động với mọi giá trị được phân tách bằng dấu chấm. Chỉ cần nhớ nó đếm từ bên phải , không phải bên trái:

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

Nếu bạn có ít hơn 4 giá trị được phân tách bằng dấu chấm, nó sẽ trả về NULLphần còn lại (nhưng nó vẫn được tính từ phải sang trái ):

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

Tuy nhiên, đây là nơi phép màu xuất hiện: kết hợp nó với STRING_SPLIT(2016 hoặc cao hơn) để tạo các bảng nhiều cột trong bộ nhớ !!

Cũ và vỡ:

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

Độ nóng mới:

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

Rõ ràng khoản tiết kiệm thực tế của bạn phụ thuộc vào kích thước và nội dung của bảng và cách chính xác bạn đang sử dụng nó.

Lưu ý rằng nếu các trường của bạn có chiều rộng không đổi, có lẽ bạn nên sử dụng LEFTRIGHTtách chúng ra thay vì PARSENAME(không chỉ vì tên hàm ngắn hơn mà còn vì bạn có thể loại bỏ hoàn toàn dấu phân cách).


Tôi không chắc chắn khi PARSENAME xuất hiện, nhưng có những bài viết mô tả nó từ năm 2003
t-clausen.dk

1

Một vài thủ thuật không liên quan mà tôi đã thấy và muốn giữ gìn:

  1. Sử dụng GO #để lặp lại một khối một số lần cụ thể .

Xem mẹo thông minh này trên câu trả lời tuyệt vời của Paul .

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

Tất nhiên, điều này sẽ đặt lại bất kỳ biến đếm nào trong khối, vì vậy bạn phải cân nhắc điều này với WHILEvòng lặp hoặc x: ... GOTO xvòng lặp.

  1. SELECT TOP ... FROM systypes

Từ câu hỏi tương tự như của Paul ở trên, Anuj Tripathi đã sử dụng mẹo sau :

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

hoặc, như được đề xuất bởi Pinkfloydx33 trong các bình luận:

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

Lưu ý đây không dựa trên bất kỳ thực tế nội dung của systypes, chỉ là quan điểm hệ thống tồn tại (mà nó làm trong mỗi cơ sở dữ liệu MS SQL), và chứa ít nhất 10 dòng (có vẻ chứa 34 tuổi, đối với hầu hết các phiên bản gần đây của SQL ). Tôi không thể tìm thấy bất kỳ chế độ xem hệ thống nào có tên ngắn hơn (không yêu cầu sys.tiền tố), vì vậy điều này có thể lý tưởng.


1

Xem câu hỏi này trên dba.stackexchange để biết một số ý tưởng thú vị để thêm một cột số vào kết quả STRINGinksLIT.

Đưa ra một chuỗi như thế 'one,two,three,four,five', chúng tôi muốn nhận được một cái gì đó như:

value   n
------ ---
one     1
two     2
three   3
four    4
five    5
  1. Theo câu trả lời của Joe Obbish, sử dụng ROW_NUMBER()và đặt hàng theo NULLhoặc hằng số:

    SELECT value, ROW_NUMBER() OVER(ORDER BY (SELECT 1))n
    FROM STRING_SPLIT('one,two,three,four,five',',')
    
  2. Mỗi câu trả lời của Paul White, hãy sử dụngSEQUENCE :

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

Trình tự là các đối tượng liên tục thú vị; bạn có thể xác định loại dữ liệu, giá trị tối thiểu và tối đa, khoảng thời gian và liệu nó có bao bọc xung quanh từ đầu không:

    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. Mỗi câu trả lời Biju jose, bạn có thể sử dụng các IDENTITY() chức năng (đó là không giống như các IDENTITY tài sản kết hợp với một INSERT:

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

Lưu ý rằng hai tham số cuối cùng trong IDENTITY(INT,1,1)là tùy chọn và sẽ mặc định là 1 nếu bị loại trừ.


vấn đề là STRINGinksLIT không đảm bảo bất kỳ lệnh trả lại nào. Bạn có thể nghĩ rằng nó sẽ luôn trả về các hàng theo thứ tự các mã thông báo trong chuỗi ban đầu. Quả thực nó có thể làm điều đó! Tuy nhiên, không có gì đảm bảo trong các tài liệu. Sẽ tốt thôi nếu bạn không quan tâm đến đơn hàng. Nhưng nếu bạn làm (ví dụ: phân tích một hàng ở định dạng CSV), sẽ có một vấn đề.
user1443098

1
@ user1443098 Cuối cùng tôi đồng ý với bạn trong bối cảnh đề xuất mã cho mục đích kinh doanh, như chúng ta có thể thấy trên dba.SE. Nhưng đối với những thách thức trên PPCG, tiêu chuẩn của tôi hơi khác một chút; nếu trong kiểm tra mã của tôi trả về các hàng theo thứ tự tôi muốn thì tôi sẽ lưu các byte ở nơi tôi có thể. Tương tự như cách tôi sẽ bỏ qua ORDER BYnếu tôi có thể thoát khỏi nó (xem câu trả lời của tôi về Toasty, Burnt, Brulee chẳng hạn).
BradC

1

Chỉ cần phát hiện ra rằng bạn có thể sử dụng chữ số cho một ký tự REPLACEđể loại bỏ dấu ngoặc kép :

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

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

Điều này là do REPLACEkhông chuyển đổi ngầm định thành chuỗi.

Cả hai đều tạo ra cùng một đầu ra:

Baby Shark doo doo doo doo doo doo

0

_ và # là các bí danh hợp lệ. Tôi sử dụng chúng với CROSS ỨNG DỤNG để làm cho nó xuất hiện các cột mà nó trả về là một phần của mệnh đề TỪ, vd

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

Tôi thích điều này khi mục đích duy nhất của ỨNG DỤNG CROSS là tính toán một biểu thức.

Đối với vấn đề đó, sử dụng ỨNG DỤNG để tính toán các biểu thức con là một cách gọn gàng để làm cho mã của bạn DRY-er (và ngắn hơn). Từ những gì tôi đã thấy trong các kế hoạch thực hiện, không có chi phí bổ sung cho phương pháp này. Trình biên dịch chỉ ra rằng bạn chỉ đang tính toán một cái gì đó và coi nó như bất kỳ biểu thức nào khác.


Tôi tìm thấy áp dụng chéo trong thời gian dài, thực sự rất khó để tìm thấy một tình huống hữu ích bằng cách sử dụng áp dụng chéo mà không tìm thấy một phương pháp ngắn hơn khác
t-clausen.dk

OK - rút ngắn ví dụ nêu trên!
user1443098

CHỌN 10 số, số * 2 n2 TỪ master.dbo.spt_values ​​v
t-clausen.dk

Ý tôi là, giữ sự tham gia. Nhân tiện, một khi bạn xây dựng các truy vấn xml, CROSS ỨNG DỤNG có thể trở thành cách duy nhất để làm điều đó, vì có thể không có cột nào trong truy vấn con thực hiện tham gia.
user1443098

Thuê bao ngắn hơn áp dụng chéo: CHỌN top 10 * TỪ (CHỌN số n, số *
2n2 TỪ chủ..spt_values
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.