WHERE句での列エイリアスの参照


166
SELECT logcount, logUserID, maxlogtm
   , DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary
WHERE daysdiff > 120

私は得る

「無効な列名daysdiff」。

Maxlogtmは日時フィールドです。それは私を夢中にさせる小さなものです。


mysqlについては不明ですが、エイリアスをティックでラップする必要があるかもしれません`daysdiff`
Ash Burlaczenko 2011

回答:


194
SELECT
   logcount, logUserID, maxlogtm,
   DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary
WHERE ( DATEDIFF(day, maxlogtm, GETDATE() > 120)

通常、WHERE句のフィールドエイリアスを参照することはできません。(SELECTエイリアスを含む全体として考えると、WHERE句の後に適用されます。)

ただし、他の回答で述べたように、SQLを強制的に処理SELECTして、WHERE句の前に処理することができます。これは通常、操作の論理的な順序を強制する括弧で、または共通テーブル式(CTE)で行われます。

括弧/副選択:

SELECT
   *
FROM
(
   SELECT
      logcount, logUserID, maxlogtm,
      DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
   FROM statslogsummary   
) as innerTable
WHERE daysdiff > 120

または、同じのCTEバージョンに関するAdamの回答を参照してください。


16
年代順に、WHEREはSELECTの前に発生するため、これは直接実行できません。SELECTは常に実行チェーンの最後のステップです。REFER - stackoverflow.com/questions/356675/...
デビッドブレイン

選択のエイリアスが相関サブクエリの場合、これは機能しますが、CTEソリューションは機能しません。
–RăzvanFlavius Panda 2016

Pascalが彼の回答であるstackoverflow.com/a/38822328/282887で述べているように、サブクエリよりも高速に動作するように見えるHAVING句を使用できます。
Bakhtiyor

@BakhtiyorこのHAVING質問が関係するMS-SQLを含むほとんどのSQL環境では、答えは機能しません。(T-SQL HAVINGでは、集約関数が必要です。)
Jamie F

72

エイリアスをWHERE句で使用する場合は、サブ選択またはCTEでラップする必要があります。

WITH LogDateDiff AS
(
   SELECT logcount, logUserID, maxlogtm
      , DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
   FROM statslogsummary
)
SELECT logCount, logUserId, maxlogtm, daysdiff
FROM LogDateDiff
WHERE daysdiff > 120

2
あなたはたまたまこれがどのように効率を公平にするか知っていますか?CTEを使用すると追加のオーバーヘッドはありますか?
ジェームズ

5
CTEはサブクエリのより洗練された構文なので、パフォーマンスはそれに似ています。私の経験では、パフォーマンスの違いはこのような操作に関係するものではありませんでしたが、環境でテストして特定のテーブル/クエリがこれに悪影響を及ぼしているかどうかを確認するのはかなり簡単です具体的にはwhere句の式。あなたは違いに気付かないでしょう。
Adam Wenger 14

CTEは、サブクエリとして使用するまでは非常に優れています。それらをネストするためのビューとして作成する必要がありました。私はこれを深刻なSQLの欠点だと考えています
シンビオント2017

10

コードを繰り返さずにそれを行う最も効果的な方法は、WHEREではなくHAVINGを使用することです

SELECT logcount, logUserID, maxlogtm
   , DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary
HAVING daysdiff > 120

1
HAVINGエイリアスでの使用は標準ではないと思います(ただし、MySQLでは機能します)。具体的には、SQL Serverでは機能しないと思います。
tokland 2016年

2
SQL Server:[S0001][207] Invalid column name 'daysdiff'
Vadzim

3
SQL Server:[S0001][8121] Column 'day' is invalid in the HAVING clause because it is not contained in either an aggregate function or the GROUP BY clause.
Vadzim

9

すべての列をCTEで一覧表示したくない場合、これを行う別の方法は次のようにすることouter applyです:

select
    s.logcount, s.logUserID, s.maxlogtm,
    a.daysdiff
from statslogsummary as s
    outer apply (select datediff(day, s.maxlogtm, getdate()) as daysdiff) as a
where a.daysdiff > 120

6

サブクエリを使用するのはどうですか(これはMysqlで私にとってはうまくいきました)?

SELECT * from (SELECT logcount, logUserID, maxlogtm
   , DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary) as 'your_alias'
WHERE daysdiff > 120

4

HAVINGは、ドキュメントに従ってMySQLで機能します。

HAVING WHEREキーワードの集計関数を使用することができなかったので、句はSQLに追加されました。


4

列のエイリアスを参照することもできますが、次を使用して定義する必要がありますCROSS/OUTER APPLY

SELECT s.logcount, s.logUserID, s.maxlogtm, c.daysdiff
FROM statslogsummary s
CROSS APPLY (SELECT DATEDIFF(day, s.maxlogtm, GETDATE()) AS daysdiff) c
WHERE c.daysdiff > 120;

DBFiddleデモ

長所:

  • 式の単一の定義(維持するのが簡単/コピー/貼り付けの必要がない)
  • クエリ全体をCTE / outerqueryでラップする必要はありません
  • 参照する可能性 WHERE/GROUP BY/ORDER BY
  • 可能なより良いパフォーマンス(単一実行)

1
SQL Serverでのみ機能することを言及しておく価値はあります
Martin Zinovsky、2018年

1
@MartinZinovsky Questionはsql-serverand t-sql:)でタグ付けされています
Lukasz Szozda

0

それに似たものを探してここに来たが、CASEといつ、どここのような使用して終了:WHERE (CASE WHEN COLUMN1=COLUMN2 THEN '1' ELSE '0' END) = 0多分あなたは使用することができますDATEDIFFWHERE直接。何かのようなもの:

SELECT logcount, logUserID, maxlogtm
FROM statslogsummary
WHERE (DATEDIFF(day, maxlogtm, GETDATE())) > 120
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.