web-dev-qa-db-fra.com

Référence à un alias de colonne dans une clause WHERE

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

Je reçois

"nom de colonne invalide daysdiff".

Maxlogtm est un champ datetime. Ce sont les petites choses qui me rendent fou.

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

Normalement, vous ne pouvez pas faire référence à des alias de champ dans la clause WHERE. (Pensez-y que la totalité de SELECT, y compris les alias, est appliquée après la clause WHERE.)

Mais, comme mentionné dans d'autres réponses, vous pouvez forcer SQL à traiter le traitement de SELECT avant la clause WHERE. Ceci est généralement fait avec des parenthèses pour forcer l'ordre logique des opérations ou avec une expression de table commune (CTE):

Parenthèse/Sous-sélection:

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

Ou voir la réponse d'Adam pour une version CTE de la même chose.

166
Jamie F

Si vous souhaitez utiliser l'alias dans votre clause WHERE, vous devez l'envelopper dans une sous-sélection ou 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
70
Adam Wenger

Le moyen le plus efficace de le faire sans répéter votre code est d’utiliser _ AYANT au lieu de

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

Si vous ne souhaitez pas répertorier toutes vos colonnes dans CTE, vous pouvez également utiliser 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
_
8
Roman Pekar

Que diriez-vous d'utiliser une sous-requête (cela a fonctionné pour moi dans Mysql)?

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

Vous pouvez faire référence à un alias de colonne mais vous devez le définir en utilisant 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;

Démo DBFiddle

Avantages:

  • définition unique de l'expression (plus facile à maintenir/pas besoin de copier-coller)
  • pas besoin d'envelopper la requête entière avec CTE/outerquery
  • possibilité de se référer à WHERE/GROUP BY/ORDER BY
  • meilleure performance possible (exécution unique)
4
Lukasz Szozda

Ayant fonctionné dans MySQL selon la documentation:

La clause HAVING a été ajoutée à SQL car le mot clé WHERE n'a pas pu être utilisé avec des fonctions d'agrégat.

4
roier.rdz