T-SQLでのゴルフのヒント


16

T-SQLでゴルフをするための一般的なヒントは何ですか?私は、少なくともT-SQLに特有のゴルフ問題全般のコーディングに適用できるアイデアを探しています。回答ごとに1つのヒントを投稿してください。

元のアイデアをくれたMarcogに感謝します。:)


ヒント-ゴルフには別の言語を使用してください。SQLの回答は、通常、非常に少ない、またはまったく投票されません。
t-clausen.dk

回答:


16

私の一般的なトリック::

  • @ t-sqlの有効な変数です。
  • T-sql 2012 iifはVBスタイルのcaseステートメントを追加しました。これは、ほとんどの場合、同等のものよりも短くなりif elseます。
  • \マネータイプで数値を0に初期化する便利な方法です。を追加すると、値をfloatに変換でき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)

たとえば、これら2つは意味的に同等です。

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

を使用Valuesして、テーブルまたはサブクエリを作成できます。これは、いくつかの定数行が必要な場合にのみ実際にメリットがあります。


私にとっては、お金の種類で数値を0として初期化するために、$は\よりも明確です。YMMV
user1443098

5

SQLを使用したコード圧縮

SQLは冗長で、スコアが高く、私たちが愛する限り、SELECT FROM WHERE使用するたびに23バイトかかります。これらおよび他の繰り返される単語またはコードスニペット全体を圧縮できます。これを行うと、繰り返されるコードの限界コストが1バイトに減少します!*

仕組み:

  • 変数が宣言され、圧縮されたSQLコードが割り当てられます
  • テーブルが変数を変更します。各行が変数を収縮させます。
  • 変更された変数が実行されます。

問題:

初期費用は100バイトに近く、置換テーブルの各行にはさらに6バイトかかります。この種類のロジックは、トリミングできない多くのコードで作業している場合や、チャレンジが圧縮ベースである場合を除き、あまり効果的ではありません。

ここに例があります

課題は、nまでの最後の10の2、3、および5の倍数を取得することです。これ(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バイトのgolfedです。

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()して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文字長くなります。(
ジェイコブ14

1
これを短くすることができることに注意してください。Ltrimselect(select ... for xml path( ''))はを返すため、必要ありませんnvarchar(max)。また、列の問題を解決するには、非変化式を使用します。あなたができる数値の場合v+0、文字列の場合は空の文字列を追加します。私はこれをゴルフのヒントとは本当に考えていませんが、これは悲しいことにSQLサーバーでクエリを書く方法の現実です。
マイケルB 14

3

T-SQLでビット演算子を使用することは可能です。

具体的な例はありませんが、T-SQLでゴルフをするときに知っておくべき事実だと思います。


1
これは非常に有効です。のような条件x=0 or y=0を記述する代わりに、x|y=0かなり多くのバイトを節約する論理的に同等なものとして記述することができます!
マイケルB 14


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 VARBINARYフィールドに格納される場合)を返しますが、長い、文字数(生の16進数)です。

以前にこれで遊んだことがありますが、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の好意による解凍コードの短いバージョン:

CASTを使用して外部を暗黙的な変換に変更することにより、10バイトを節約します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)')))

これ自体はわずかに長くなりますが、他の理由で変数で必要な場合は役立つかもしれません。


いいですね、SQL
はわかり

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:複数の列をまとめてマッシュすることを検討する

同じ出力を返す2つのバリエーションを次に示します。

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行以下で短く見え、一番下のバージョン(LEFTとSUBSTRINGのため)は8行以上短くなります。正確なデータに応じて、走行距離は異なる場合があります。

5:非常に長いテキストシーケンスにはREPLACEおよびEXECを使用する

静脈ではcomfortablydreiの優秀な答えは、あなたが持っている場合は、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()+、バイトを保存するように変更しました)。


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_SPLITSQL 2016以降

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

テーブルのエイリアスを作成するか、列名を参照する必要がある場合:

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

TRIMSQL 2017以降

よりRTRIM()短く、確かに短いLTRIM(RTRIM())

また、先頭または末尾から他の文字または文字セットを削除するオプションあります

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

戻り値 L Server 2

TRANSLATESQL 2017以降

TRANSLATE一連のネストされたREPLACEステートメントではなく、1つのステップで複数の文字を置換できます。お祝いしません。しかし、あまりにも多くの、それだけで別の単一文字で個々の単一の文字を置き換えます。

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

2番目の文字列の各文字は、3番目の文字列の対応する文字に置き換えられます。

次のようなものでたくさんのキャラクターを排除できるように見えます REPLACE(TRANSLATE('source string','ABCD','XXXX'),'X','')


いくつかのより興味深いものにも、同様CONCAT_WSSTRING_AGG同様、おそらく一見の価値があります。


1

神聖な牛、私はPARSENAMESQL 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','-')

明らかに、実際の節約は、テーブルのサイズと内容、および使用方法によって異なります。

フィールドが固定幅の場合は、代わりにを使用しLEFTRIGHT代わりにそれらを分離する方がよいことに注意してくださいPARSENAME(関数名が短いだけでなく、セパレータを完全に削除できるためです)。


PARSENAMEがいつ発表されたかはわかりませんが、2003年からそれを説明する記事があります
t-clausen.dk

1

私が見た、保存したかった、いくつかの無関係なトリック

  1. GO #特定の回数ブロックを繰り返すために使用します。

ポールのすばらしい答えについて、この巧妙なトリックを見ました。

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

もちろん、これはブロック内のカウンター変数をリセットするため、WHILEループまたはループと比較する必要がありx: ... GOTO xます。

  1. SELECT TOP ... FROM systypes

上記のポールと同じ質問から、アヌジトリパティは次のトリックを使用しました

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

または、コメントでpinkfloydx33が示唆しているように:

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

これは実際のいずれにも依存しないことに注意してください コンテンツsystypes、システムビューが存在する(すべてのMS SQLデータベースに存在する)だけで、少なくとも10行を含む(SQLの最新バージョンでは34を含むように見える) )。短い名前(sys.プレフィックスを必要としない)のシステムビューが見つからなかったため、これが理想的です。


1

dba.stackexchangeでこの質問を参照してくださいSTRING_SPLITの結果に数値列を追加するための興味深いアイデア。

のような文字列が与えられた場合、'one,two,three,four,five'次のようなものを取得します。

value   n
------ ---
one     1
two     2
three   3
four    4
five    5
  1. ジョー・オブビッシュの回答、使用ROW_NUMBER()および順序、NULLまたは定数:

    SELECT value, ROW_NUMBER() OVER(ORDER BY (SELECT 1))n
    FROM STRING_SPLIT('one,two,three,four,five',',')
    
  2. ポール・ホワイトの答えは1、使用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. Bijuホセの答えごとに、あなたは使用することができる機能である(ないと同じ性質 INSERTと組み合わせての:IDENTITY() IDENTITY

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

の最後の2つのパラメーター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

SELECT TOP 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.