Посилання на псевдонім стовпця в пункті WHERE


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

я отримав

"недійсна назва стовпця".

Maxlogtm - це поле дати. Саме ця штучка зводить мене з розуму.


не впевнений у mysql, але, можливо, псевдонім потрібно загорнути в кліщі `daysdiff`.
Еш Бурлаценко

Відповіді:


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.


16
Це неможливо безпосередньо, оскільки в хронологічному відношенні ТОГО відбувається перед SELECT, який завжди є останнім кроком у ланцюжку виконання. ДИВІТЬСЯ - stackoverflow.com/questions/356675 / ...
Девід Блейн

afaik, якщо псевдонім у select є корельованим підзапитом, це буде працювати, поки рішення CTE не буде.
Пазва Развана Флавія

Як Паскаль згадував у своїй відповіді тут stackoverflow.com/a/38822328/282887 , ви можете використовувати пункт HAVING, який, здається, працює швидше, ніж підзапити.
Бахтиер

@Bakhtiyor HAVINGВідповідь не працює в більшості середовищ SQL, включаючи MS-SQL, про який йдеться у цьому питанні. (У T-SQL HAVINGпотрібна сукупна функція.)
Джеймі Ф

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 - це просто кращий синтаксис для підзапиту, тому продуктивність буде подібною до такої. З мого досвіду, різниця в продуктивності не стосувалася мене для таких операцій, але слід досить просто перевірити це у вашому оточенні, щоб побачити, чи не впливає ваша конкретна таблиця / запит на це порівняно з викликом формула конкретно в пункті де. Я підозрюю, що ви не помітите різниці.
Адам Венгер

CTE дуже приємні, поки ви не спробуєте використати його як підзапит. Мені довелося вдатися до їх створення як виду, щоб гніздити їх. Я вважаю це серйозним недоліком SQL
симбіонт

10

Найефективніший спосіб зробити це без повторення коду - це використання HAVING замість WHERE

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

1
Я думаю, що використання HAVINGпсевдонімів не є стандартним (хоча воно працює і на MySQL). Зокрема, я думаю, що це не працює з SQL Server.
токленд

2
SQL Server:[S0001][207] Invalid column name 'daysdiff'
Вадим

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.
Вадим

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 відповідно до документації:

У SQL було додано пропозицію HAVING, оскільки ключове слово WHERE неможливо було використовувати з агрегованими функціями.


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 / externalquery
  • можливість посилатися WHERE/GROUP BY/ORDER BY
  • можливі кращі показники (одноразове виконання)

1
Варто зазначити, що він працює лише у SQL Server
Мартін Зіновський,

1
@MartinZinovsky Питання позначено тегами sql-serverі t-sql:)
Лукаш Шозда

0

Приїхав сюди в пошуках що - щось подібне, але з випадком , коли, і закінчився , використовуючи , де , як це: WHERE (CASE WHEN COLUMN1=COLUMN2 THEN '1' ELSE '0' END) = 0може бути , ви могли б використовувати DATEDIFFв WHEREбезпосередньо. Щось на зразок:

SELECT logcount, logUserID, maxlogtm
FROM statslogsummary
WHERE (DATEDIFF(day, maxlogtm, GETDATE())) > 120
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.