WHERE Yan tümcesinde Sütun Takma Adına Başvurma


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

alırım

"geçersiz sütun adı daysdiff".

Maxlogtm bir datetime alanıdır. Beni çıldırtan küçük şeyler.


mysql için emin değilim, ama belki takma adın kenelere sarılması gerekir `daysdiff`.
Ash Burlaczenko

Yanıtlar:


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

Normalde, WHEREyan tümcedeki alan takma adlarına başvuramazsınız. (Diğer SELECTadlar da dahil olmak üzere tümünün , WHEREmaddeden sonra uygulandığını düşünün .)

Ancak, diğer yanıtlarda belirtildiği gibi, SQL'i maddeden SELECTönce ele alınmaya zorlayabilirsiniz WHERE. Bu genellikle mantıksal işlem sırasını zorlamak için parantez veya Ortak Tablo İfadesi (CTE) ile yapılır:

Parantez / Alt Seçim:

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

Veya Adem'in aynı CTE sürümü için cevabına bakın.


16
Bu doğrudan mümkün değildir, çünkü kronolojik olarak, her zaman yürütme zincirindeki son adım olan SELECT'ten önce NEREDE gerçekleşir. - REFER stackoverflow.com/questions/356675/...
david Blaine

afaik, seçimdeki takma ad ilişkili bir alt sorgu ise CTE çözümü çalışmazken çalışır.
Răzvan Flavius ​​Panda

Pascal'ın cevabında belirttiği gibi stackoverflow.com/a/38822328/282887 , alt sorgulardan daha hızlı çalışıyor gibi görünen HAVING yan tümcesini kullanabilirsiniz.
Mayıs 1919'da

@Bakhtiyor HAVINGYanıt, bu sorunun söz konusu olduğu MS-SQL de dahil olmak üzere çoğu SQL ortamında çalışmaz. (T-SQL'de HAVINGbir toplama işlevi gerektirir.)
Jamie F

72

Cümlenizdeki diğer adı kullanmak istiyorsanız WHERE, onu bir alt seçime veya CTE'ye sarmanız gerekir :

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
Bu fuarların verimliliğini nasıl akıllıca bildiğinizi biliyor musunuz? CTE kullanarak ek yük var mı?
James

5
Bir CTE, bir alt sorgu için daha güzel bir sözdizimidir, bu nedenle performans buna benzer olacaktır. Deneyimlerime göre, performans farkı, böyle işlemler için beni ilgilendiren bir şey değildi, ancak belirli tablonuzun / sorgunuzun bu durumdan olumsuz etkilenip etkilenmediğini görmek için ortamınızda test etmek oldukça basit olmalıdır. formül özellikle nerede yan tümcesinde. Bir fark görmeyeceğinizden şüpheleniyorum.
Adam Wenger

CTE'ler, alt sorgu olarak kullanmaya çalışana kadar süper iyidir. onları iç içe görünüm olarak oluşturmak için başvurmak zorunda kaldı. Ben bu ciddi bir SQL eksikliği düşünün
symbiont

10

Kodunuzu tekrar etmeden bunu yapmanın en etkili yolu NEREDE yerine HAVING kullanmaktır.

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

1
HAVINGTakma adlarda kullanmak standart değil (MySQL üzerinde çalışıyor olsa da) düşünüyorum. Özellikle, SQL Server ile çalışmadığını düşünüyorum.
tokland

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'deki tüm sütunlarınızı listelemek istemiyorsanız, bunu yapmanın başka bir yolu da kullanmaktır 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

Bir alt sorgu kullanmaya ne dersiniz (bu benim için Mysql'de işe yaradı)?

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

4

HAVING, belgelere göre MySQL'de çalışır:

HAVING NEREDE kelime toplama işlevleri kullanılamaz çünkü tümcesi SQL eklendi.


4

Sütun takma adına başvurabilirsiniz, ancak şunu kullanarak tanımlamanız gerekir 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 Demosu

Artıları:

  • tek ifade tanımı (bakımı daha kolay / kopyalama-yapıştırma ihtiyacı yok)
  • tüm sorguyu CTE / dış sorgu ile sarmaya gerek yok
  • referans alma imkanı WHERE/GROUP BY/ORDER BY
  • olası daha iyi performans (tek uygulama)

1
sadece SQL Server'da çalıştığını belirtmeye değer
Martin Zinovsky

1
@MartinZinovsky Soru ile etiketlendi sql-serverve t-sql:)
Lukasz Szozda

0

Buraya geldi buna benzer bir şey arıyorum ama HALİNDE ile ZAMAN ve yerde de böyle kullanılarak bitti: WHERE (CASE WHEN COLUMN1=COLUMN2 THEN '1' ELSE '0' END) = 0belki kullanabilirsiniz DATEDIFFiçinde WHEREdoğrudan. Gibi bir şey:

SELECT logcount, logUserID, maxlogtm
FROM statslogsummary
WHERE (DATEDIFF(day, maxlogtm, GETDATE())) > 120
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.