web-dev-qa-db-fra.com

Comment utiliser le nom de colonne d'alias dans la clause où dans SQL Server

Lorsque j'essaie d'exécuter le code ci-dessous dans SQL Server 2005, le message d'erreur s'affiche. 

Nom de colonne invalide DistanceFromAddress

Code:

select 
    SQRT(POWER(cast(Program_Latitude as float) - cast('41.5126237' as float), 2) +   
    POWER(cast(Program_Longitude as float) - cast('-81.6516411' as float), 2)) * 62.1371192 AS DistanceFromAddress 
from 
    tblProgram 
where 
    DistanceFromAddress < 2

J'obtiens les valeurs correctement en utilisant l'instruction select, mais quand j'ai essayé de vérifier la condition where DistanceFromAddress < 2, j'obtiens l'erreur.

Comment puis-je résoudre ce problème?

35
Kannan

Vous ne pouvez pas utiliser de colonnes avec alias dans une clause WHERE. Vous pouvez essayer d'utiliser une table dérivée. Peut-être quelque chose comme ça (désolé, pas testé):

SELECT * FROM
(SELECT SQRT(POWER(cast(Program_Latitude as float) - cast('41.5126237' as float), 2) +   
 POWER(cast(Program_Longitude as float) - cast('-81.6516411' as float), 2)) * 62.1371192 
 AS DistanceFromAddress from tblProgram) mytable
WHERE DistanceFromAddress < 2
37
Steven Wolfe

La clause WHERE est traitée avant la clause SELECT (*) ​​et les alias ne sont donc pas disponibles. Passez à l'aide d'une sous-requête ou CTE - voici un CTE:

; with Distances as (
    select SQRT(POWER(cast(Program_Latitude as float) - cast('41.5126237' as float), 2) +   
 POWER(cast(Program_Longitude as float) - cast('-81.6516411' as float), 2)) * 62.1371192 
 AS DistanceFromAddress
    from tblProgram
)
select * from Distances where DistanceFromAddress < 2

(*) - eh bien, les systèmes sont libres de réorganiser les opérations comme bon leur semble, tant que le résultat est "comme si" l'instruction SQL avait été traitée dans un certain ordre logique . Bien entendu, lorsque tout cela ne va pas avec SQL Server, c'est produit des erreurs en raison de problèmes de conversion dans la clause SELECT pour les lignes/valeurs qui devraient être éliminées par la clause WHERE.

26
select 
  SQRT(
    POWER(cast(Program_Latitude as float) - cast('41.5126237' as float), 2) +
    POWER(cast(Program_Longitude as float) - cast('-81.6516411' as float), 2)
  ) * 62.1371192 AS DistanceFromAddress 
from tblProgram 
having DistanceFromAddress < 2

pourrait fonctionner (bien que je ne le pense pas, sans un groupe par article également).

Le problème est que vous ne pouvez utiliser que des noms dans la portée de la ou des tables sélectionnées dans la clause where. Where est un pré-filtre qui filtre les lignes avant leur sélection. Les expressions telles que celle-ci dans la définition du champ ne sont pas encore exécutées et les alias ne sont donc pas disponibles. 

La clause Having fonctionne comme un post-filtre après le regroupement et peut utiliser les alias de la requête, bien que je crains que vous n’ayez besoin de disposer d’une clause group by réelle (incertain).

L'alternative consiste à avoir une sous-sélection (table dérivée ou sélection dans sélection), où vous sélectionnez d'abord les distances pour chaque ligne, puis sélectionnez uniquement les distances pertinentes à partir de ces résultats. Cela fonctionnera:

select d.DistanceFromAddress
from
  (select 
    SQRT(
      POWER(cast(Program_Latitude as float) - cast('41.5126237' as float), 2) +
      POWER(cast(Program_Longitude as float) - cast('-81.6516411' as float), 2)
    ) * 62.1371192 AS DistanceFromAddress 
  from tblProgram) d
where d.DistanceFromAddress < 2

Ou vous pouvez répéter l'expression. Cela rend votre requête plus difficile à gérer, mais dans certains cas, cela peut fonctionner pour vous. Par exemple, si vous ne souhaitez pas renvoyer la distance réelle, mais uniquement, par exemple, le nom du point d’intérêt situé à cette distance. Dans ce cas, vous devez disposer de l'expression only dans la clause where, auquel cas l'argument de maintenabilité a disparu, et cette solution constitue une alternative parfaite.

select 
  tblProgram.POIname
  /* Only if you need to return the actual value
  , SQRT(
    POWER(cast(Program_Latitude as float) - cast('41.5126237' as float), 2) +
    POWER(cast(Program_Longitude as float) - cast('-81.6516411' as float), 2)
  ) * 62.1371192 AS DistanceFromAddress */
from tblProgram
where 
  -- Use this if you only want to filter by the value.
  SQRT(
    POWER(cast(Program_Latitude as float) - cast('41.5126237' as float), 2) +
    POWER(cast(Program_Longitude as float) - cast('-81.6516411' as float), 2)
  ) * 62.1371192 < 2
1
GolezTrol

Je pense que vous ne pouvez utiliser AS que pour afficher les valeurs finales. Pour faire une comparaison, la sélection doit être renvoyée par une autre instruction select à l'intérieur de celle-ci.

Comme:

SELECT a.disfromaddr FROM
 ( SELECT SQRT(POWER(cast(Program_Latitude as float) - cast('41.5126237' as float), 2) +   
 POWER(cast(Program_Longitude as float) - cast('-81.6516411' as float), 2)) * 62.1371192 
 AS DistanceFromAddress FROM tblProgram) 
a WHERE a.disfromaddr < 2

Vous pouvez essayer ça.

0
openrijal