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?
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
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
.
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
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.