คุณมีเคล็ดลับทั่วไปอะไรสำหรับการเล่นกอล์ฟใน T-SQL ฉันกำลังมองหาแนวคิดที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟโดยทั่วไปซึ่งอย่างน้อยค่อนข้างเฉพาะกับ T-SQL กรุณาโพสต์หนึ่งเคล็ดลับต่อคำตอบ
ขอบคุณ Marcog สำหรับแนวคิดดั้งเดิม :)
คุณมีเคล็ดลับทั่วไปอะไรสำหรับการเล่นกอล์ฟใน T-SQL ฉันกำลังมองหาแนวคิดที่สามารถนำไปใช้กับปัญหารหัสกอล์ฟโดยทั่วไปซึ่งอย่างน้อยค่อนข้างเฉพาะกับ T-SQL กรุณาโพสต์หนึ่งเคล็ดลับต่อคำตอบ
ขอบคุณ Marcog สำหรับแนวคิดดั้งเดิม :)
คำตอบ:
กระเป๋าทั่วไปของฉันของเทคนิค ::
@
เป็นตัวแปรที่ถูกต้องใน t-sqliif
คำสั่งกรณีสไตล์ VB if
else
นี้มักจะสั้นกว่าเทียบเท่า\
เป็นวิธีที่มีประโยชน์ในการเริ่มต้นตัวเลขเป็น 0 ในประเภทเงิน e
คุณสามารถแปลงค่าให้กับการลอยโดยการเพิ่ม เช่น4e
หรือ\k
ซึ่งจะตั้งค่า k เป็นค่า 0.00 เงินrCTE
ดูเหมือนจะเป็นวิธีที่ดีที่สุดในการสร้างตารางตัวเลขที่น้อยกว่า 100 รายการ ยิ่งสั้นกว่าการใช้ spt_values หากคุณต้องการมากกว่า 100 ข้ามเข้าร่วมและเพิ่มพวกเขา+=
และผู้ประกอบการผสมอื่น ๆ ถูกเพิ่มเข้ามาในปี 2008 ใช้พวกมันเพื่อบันทึกอักขระสองสามตัว;
คุณแทบจะไม่ต้องเป็นพื้นที่หรือSelect*from A,B where condition
สั้นกว่าselect*from A join b on condition
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
เพื่อสร้างตารางหรือแบบสอบถามย่อย นี่จะเป็นประโยชน์จริงๆถ้าคุณต้องการค่าคงที่สองสามแถว
การบีบอัดรหัสโดยใช้ SQL
SQL นั้นใช้คำพูดได้คะแนนสูงและมากเท่ากับที่เรารักมีSELECT FROM WHERE
ค่า 23 ไบต์ทุกการใช้งาน คุณสามารถบีบอัดคำเหล่านี้และคำซ้ำ ๆ หรือตัวอย่างโค้ดทั้งหมด การทำเช่นนี้จะช่วยลดต้นทุนส่วนต่างของรหัสซ้ำเป็น 1 ไบต์! *
มันทำงานอย่างไร:
ปัญหา:
ค่าใช้จ่ายล่วงหน้าอยู่ใกล้กับ 100 ไบต์และแต่ละแถวในตารางการแทนที่มีค่าใช้จ่ายอีก 6 ไบต์ ตรรกะชนิดนี้จะไม่ได้ผลมากเว้นแต่คุณจะทำงานกับโค้ดจำนวนมากซึ่งคุณไม่สามารถตัดทอนหรือความท้าทายนั้นมาจากการบีบอัด
นี่คือตัวอย่าง
ความท้าทายคือการได้ทวีคูณ 10 เท่าของ 2,3 และ 5 นำไปสู่ n สมมติว่านี่ ( 343 ไบต์ 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)
SELECT @=REPLACE(@,i,j)FROM(VALUES(...)x(i,j)
แทนการใช้คอลัมน์เดียวกับและLEFT()
SUBSTRING()
หากคุณมี 8 คนขึ้นไปการหลีกเลี่ยงการเพิ่มราคาและเครื่องหมายจุลภาคเป็นการแลกเปลี่ยนที่ดี
SET @=REPLACE(REPLACE(REPLACE(...
นี่เป็นเรื่องตลก สิ่งนี้จะแปลงค่าในคอลัมน์เป็น tuple เดียว
แก้ไข: ขอบคุณสำหรับความคิดเห็น ดูเหมือนว่าวิธีที่สั้นที่สุดในการเลื่อนโดยไม่มีแท็ก XML คือ:
SELECT (SELECT column1+''
FROM table
ORDER BY column1
FOR XML PATH(''))
หมายเหตุ: ถ้า XML เป็นเอาต์พุตที่ถูกต้องคุณสามารถละเว้นการเลือก outer และ parens นอกจากนี้ยังใช้column1+''
งานได้กับสตริงเท่านั้น สำหรับประเภทหมายเลขจะดีที่สุดที่จะทำcolumn1+0
<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 ของคุณ :(
Ltrim
ไม่จำเป็นต้องเป็นเลือก (เลือก ... สำหรับเส้นทาง XML ( '')) nvarchar(max)
ส่งกลับ นอกจากนี้เพื่อแก้ปัญหาคอลัมน์เพียงแค่ใช้การแสดงออกที่ไม่กลายพันธุ์ สำหรับตัวเลขที่คุณสามารถทำได้v+0
สำหรับสตริงเพิ่มสตริงว่างเปล่า ฯลฯ แม้ว่าฉันจะไม่คิดว่านี่เป็นเคล็ดลับการเล่นกอล์ฟ แต่นี่เป็นเพียงความเศร้าของความเป็นจริงของวิธีการเขียนแบบสอบถามในเซิร์ฟเวอร์ sql
มันเป็นไปได้ที่จะใช้บางบิตผู้ประกอบการใน T-SQL
ฉันไม่มีตัวอย่างที่เป็นรูปธรรม แต่ฉันเชื่อว่ามันเป็นความจริงที่รู้กันดีเมื่อเล่นกอล์ฟใน T-SQL
x=0 or y=0
คุณสามารถเขียนสิ่งนั้นในฐานะที่เทียบเท่าเชิงตรรกะx|y=0
ซึ่งช่วยประหยัดได้ไม่กี่ไบต์!
มันง่ายอย่างนั้น! ดังนั้นนี่คือรูปหลายภาษา T-SQL / Python:
print'Hello, World!'
สัญกรณ์วิทยาศาสตร์เป็นวิธีที่สั้นกว่าที่จะแสดงตัวเลขขนาดใหญ่มากและมีขนาดเล็กมากเช่นselect 1000000000
= select 1E9
และ=select 0.000001
select 1E-6
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
ดังนั้นฉันจึงรู้ว่า SQL 2016 ได้เพิ่มCOMPRESS
ฟังก์ชั่น (และ a)DECOMPRESS
ฟังก์ชั่น) ซึ่ง (ในที่สุด) นำความสามารถในการ GZIP สตริงหรือไบนารี
ปัญหาคือมันไม่ชัดเจนในทันทีว่าจะใช้ประโยชน์จากสิ่งนี้เพื่อเล่นกอล์ฟ; COMPRESS
สามารถใช้สตริง แต่ส่งกลับ a VARBINARY
ซึ่งสั้นกว่าเป็นไบต์ (เมื่อเก็บไว้ในVARBINARY
เขตข้อมูลSQL ) แต่จะยาวกว่าในตัวอักษร (hex ดิบ)
ฉันเคยเล่นมาก่อนหน้านี้ แต่ในที่สุดฉันก็สามารถรวบรวมเวอร์ชั่นที่ใช้งานได้ตามคำตอบเก่า ๆ ของ SOคำตอบนี้เก่าในดังนั้นโพสต์นั้นไม่ได้ใช้ฟังก์ชัน GZIP ใหม่ แต่แปลงเป็น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 :
บันทึก 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)')))
ตัวมันเองจะยาวกว่านี้เล็กน้อยแต่ถ้าคุณต้องการตัวแปรในเหตุผลอื่นก็อาจช่วยได้
ความคิดเล็กน้อยเกี่ยวกับการสร้างและใช้ตารางสำหรับความท้าทาย:
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 สำหรับลำดับข้อความที่ยาวมาก
ในหลอดเลือดดำของคำตอบที่ดีเยี่ยมอย่างสบายๆ ถ้าคุณมีค่า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()
เพื่อ+
ที่จะบันทึก bytes)
แท็กรหัสของคุณสำหรับการเน้นไวยากรณ์ 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
ใช้ประโยชน์จากคุณสมบัติ / ฟังก์ชั่นใหม่ใน 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_WS
และSTRING_AGG
อาจมีค่าดูเช่นกัน
วัวศักดิ์สิทธิ์ฉันได้ค้นพบความมหัศจรรย์ของ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
(ไม่ใช่เพียงเพราะชื่อฟังก์ชันสั้นกว่า แต่ยังเป็นเพราะคุณสามารถกำจัดตัวแยกทั้งหมดได้)
เคล็ดลับที่ไม่เกี่ยวข้องอีกสองสามข้อที่ฉันเห็นและต้องการรักษา:
GO #
เพื่อทำซ้ำบล็อกตามจำนวนครั้งที่ระบุเห็นเคล็ดลับฉลาดนี้ในคำตอบที่ดีเยี่ยมของพอล
PRINT'**********'
GO 10
แน่นอนว่าสิ่งนี้จะรีเซ็ตตัวแปรตัวนับใด ๆ ในบล็อกดังนั้นคุณต้องชั่งน้ำหนักกับWHILE
ลูปหรือx: ... GOTO x
ลูป
SELECT TOP ... FROM systypes
จากคำถามเดียวกันกับของ Paul ด้านบนAnuj Tripathi ใช้เคล็ดลับต่อไปนี้ :
SELECT TOP 10 REPLICATE('*',10) FROM systypes
หรือตามที่แนะนำโดย pinkfloydx33 ในความคิดเห็น:
SELECT TOP 10'**********'FROM systypes
หมายเหตุนี้ไม่ได้พึ่งพาใด ๆ ที่เกิดขึ้นจริงเนื้อหาของsystypes
เพียงว่ามุมมองของระบบที่มีอยู่ (ซึ่งมันไม่ได้ในทุกฐานข้อมูล MS SQL) และมีอย่างน้อย 10 แถว (มันก็ดูจะมี 34 รุ่นล่าสุดของ SQL ) ฉันไม่พบมุมมองระบบใด ๆ ที่มีชื่อที่สั้นกว่า (ที่ไม่ต้องใช้sys.
คำนำหน้า) ดังนั้นนี่อาจเหมาะ
ดู คำถามนี้ใน dba.stackexchangeสำหรับแนวคิดที่น่าสนใจสำหรับการเพิ่มคอลัมน์ตัวเลขในผลลัพธ์ STRING_SPLIT
รับสายเหมือน'one,two,three,four,five'
เราต้องการได้รับสิ่งที่ชอบ:
value n
------ ---
one 1
two 2
three 3
four 4
five 5
คำตอบของ Joe Obbish ใช้ROW_NUMBER()
และเรียงโดยNULL
หรือค่าคงที่:
SELECT value, ROW_NUMBER() OVER(ORDER BY (SELECT 1))n
FROM STRING_SPLIT('one,two,three,four,five',',')
คำตอบของ Paul White ใช้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
คำตอบต่อ Biju jose ของคุณสามารถใช้ฟังก์ชั่น (ซึ่งไม่ได้เช่นเดียวกับคุณสมบัติร่วมกับ 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 หากไม่รวม
ORDER BY
ถ้าฉันสามารถไปกับมัน (ดูคำตอบของฉันToasty, Burnt, Bruleeเป็นต้น)
เพิ่งค้นพบว่าคุณสามารถใช้ตัวเลขสำหรับตัวเดียว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
_ และ # เป็นชื่อแทนที่ถูกต้อง ฉันใช้พวกเขากับ CROSS APPLY เพื่อทำให้คอลัมน์ที่ส่งคืนนั้นเป็นส่วนหนึ่งของส่วนคำสั่ง FROM เช่น
SELECT TOP 10 number, n2
FROM master.dbo.spt_values v
CROSS APPLY (SELECT number*2 n2) _
ฉันชอบสิ่งนี้เมื่อวัตถุประสงค์เดียวของ CROSS APPLY คือการคำนวณการแสดงออก
สำหรับเรื่องนั้นการใช้ APPLY สำหรับการคำนวณนิพจน์ย่อยเป็นวิธีที่เรียบร้อยในการทำให้โค้ดของคุณแห้ง (และสั้นกว่า) จากสิ่งที่ฉันเห็นในแผนการดำเนินการไม่มีค่าใช้จ่ายเพิ่มเติมสำหรับวิธีการนี้ คอมไพเลอร์คิดว่าคุณแค่คำนวณอะไรบางอย่างแล้วปฏิบัติเหมือนมันเป็นนิพจน์อื่น ๆ