概要
論理的な理由はありません 行うができなかったはありませんが、利点は小さく、すぐには明らかにならないかもしれない落とし穴がいくつかあります。
調査結果
私はいくつかの研究を行い、いくつかの良い情報を見つけました。以下は、2012-08-09 17:49 GMTの信頼できるプライマリソース(匿名を希望する)からの直接の引用です。
SQLが最初に発明されたとき、SELECT句にはエイリアスがありませんでした。これは深刻な欠点であり、1986年頃にANSIによって言語が標準化されたときに修正されました。
この言語は、「非手続き型」、つまり、検索方法を指定せずに必要なデータを記述することを目的としていました。したがって、私が知る限り、SQL実装がクエリ全体を処理する前に解析できず、エイリアスをどこでも定義してどこでも使用できるようにする理由はありません。たとえば、次のクエリが有効でない理由はわかりません。
select name, salary + bonus as pay
from employee
where pay > 100000
これは妥当なクエリだと思いますが、一部のSQLベースのシステムでは、実装に関連した何らかの理由でエイリアスの使用に制限が導入される場合があります。SQL Serverがこれを行っていると聞いても驚くことではありません。
SQL-86標準と、なぜ最新のDBMSがエイリアスの再利用をサポートしていないのかをさらに研究することに興味がありますが、まだそれを使用する時間はありません。手始めに、ドキュメンテーションの入手先や、委員会を正確に構成した人物を見つける方法はわかりません。誰でも手伝うことができますか?また、SQL Serverの元となったSybase製品についても詳しく知りたいと思います。
この調査といくつかのさらなる考えから、他の句でエイリアスを使用することは可能ですが、他の言語機能に比べてDBMSメーカーにとってそれほど高い優先事項ではなかったのではないかと思いました。それほど大きな障害ではないため、クエリライターが簡単に回避できるため、他の進歩よりも努力するのは最適ではありません。さらに、それは明らかにSQL標準の一部ではないので独自のものとなります(確かにそれについてさらに調べるのを待っていますが)、したがって、DBMS間のSQL互換性を壊して、わずかな改善になります。比較すると、CROSS APPLY
(これは実際には外部参照を許可する派生テーブルにすぎません)は大きな変更ですが、プロプライエタリは他の方法では簡単に実行できない信じられないほどの表現力を提供します。
どこでもエイリアスを使用する際の問題
SELECT項目をWHERE句に入れることを許可すると、クエリの複雑さ(したがって、適切な実行プランを見つけることの複雑さ)を爆発させるだけでなく、完全に非論理的なものを見つけることができます。試してください:
SELECT X + 5 Y FROM MyTable WHERE Y = X
MyTableにすでに列Yがあり、WHERE句が参照している場合はどうなりますか?解決策は、CTEまたは派生テーブルを使用することです。ほとんどの場合、追加費用はかかりませんが、同じ最終結果が得られます。CTEと派生テーブルは、エイリアスを1回だけ使用できるようにすることで、少なくともあいまいさの解決を強制します。
また、FROM句でエイリアスを使用しないことは非常に理にかなっています。これはできません:
SELECT
T3.ID + (SELECT Min(Interval) FROM Intervals WHERE IntName = 'T') CalcID
FROM
Table1 T
INNER JOIN Table2 T2
ON T2.ID = CalcID
INNER JOIN Table3 T3
ON T2.ID = T3.ID
それは、(T2は密かにそのテーブルがリストに参加して提示されている前に、T3からの値を参照しているという意味で)、および循環参照ですくそ見えにくいです。これはどう:
INSERT dbo.FinalTransaction
SELECT
newid() FinalTransactionGUID,
'GUID is: ' + Convert(varchar(50), FinalTransactionGUID) TextGUID,
T.*
FROM
dbo.MyTable T
newid()関数が実行プランに2回配置され、まったく予期せずに2つの列に異なる値が表示されることに、どのくらい賭けたいですか?上記のクエリがCTEまたは派生テーブルのNレベルの深さで使用される場合はどうですか。私はあなたが想像できるよりも問題が悪いことを保証します。クエリ代数を適切に表現しているため、すでに物事は一度だけ、またはクエリプランのどの時点で評価されている場合について真剣に矛盾の問題は、とMicrosoftは述べている、それは修正されませんそれらの一部があります。予期しない結果が得られた場合、クエリを部分に分割します。連鎖参照を許可し、潜在的に非常に長い連鎖を介して循環参照を検出します。これらは非常に難しい問題です。並列処理を導入すると、作成に悪夢が生じます。
注:WHEREまたはGROUP BYでエイリアスを使用しても、newid()やrand()などの関数に関する問題に違いはありません。
再利用可能な式を作成するSQL Serverの方法
CROSS APPLY / OUTER APPLYは、SQL Serverでクエリの他の場所で使用できる式を作成する1つの方法です(FROM句の前ではありません)。
SELECT
X.CalcID
FROM
Table1 T
INNER JOIN Table3 T3
ON T.ID = T3.ID
CROSS APPLY (
SELECT
T3.ID + (SELECT Min(Interval) FROM Intervals WHERE IntName = 'T') CalcID
) X
INNER JOIN Table2 T2
ON T2.ID = X.CalcID
これは2つのことを行います。
- CROSS APPLYのすべての式が「名前空間」(ここではテーブルエイリアス、X)を取得し、その名前空間内で一意になるようにします。
- CalcIDがXから来ていることだけでなく、Xがまだ導入されていないため、テーブルT1とT3を結合するときにXから何も使用できない理由を明らかにします。
私は実際に、クロス適用が非常に好きです。それは私の忠実な友人になりました、そして、私はいつもそれを使います。部分的なUNPIVOT(ネイティブ構文を使用したPIVOT / UNPIVOTまたはUNPIVOT / PIVOTが必要)が必要ですか?CROSS APPLYで完了。何度も再利用される計算値が必要ですか?できた リンクサーバー経由の呼び出しの実行順序を厳密に強制する必要がありますか?速度の叫び声の改善で完了。1つのタイプの行のみを2行に分割する必要がありますか、または追加条件が必要ですか?できた
少なくとも、DBMS SQL Server 2005以降では、苦情の原因はこれ以上ありません。CROSSAPPLYは、あなたが望む方法で乾燥させる方法です。