Cette question est mieux formulée avec un exemple simple. Pourquoi ne puis-je pas faire cela?Utiliser les éléments composites de sélection dans la clause where
select (lastname + ', ' + firstname) as fullname
from people
where fullname = 'Bloggs, Joe'
à la place que je dois faire ceci:
select (lastname + ', ' + firstname) as fullname
from people
where (lastname + ', ' + firstname) = 'Bloggs, Joe'
qui sent mauvais pour moi.
Plus la requête est complexe, plus ce problème devient grave.
Suivi
Voici un meilleur exemple basé sur le problème du monde réel dont l'origine de la question.
SELECT ClientID,
Name,
ContractStartDate,
ContractDetails.ContractLength,
DATEADD(MONTH, ContractDetails.ContractLength, ContractStartDate)
as ContractEndDate
FROM Clients
LEFT OUTER JOIN ContractDetails
ON Clients.ClientID = ContractDetails.ClientID
WHERE DATEADD(MONTH, ContractDetails.ContractLength, ContractStartDate)
> '2009-06-30'
J'ai réécrit la requête d'utiliser une vue intégrée comme l'a suggéré. Cependant, il contient encore la répétition - mais cette fois d'une jointure.
SELECT ClientID,
Name,
contractStartDate,
ContractDetails.ContractLength,
contractEndDate
FROM (
SELECT ClientID,
Name,
ContractStartDate,
DATEADD(MONTH, ContractDetails.ContractLength, contractStartdate)
AS contractEndDate
FROM Clients
LEFT OUTER JOIN ContractDetails
on Clients.ClientID = ContractDetails.ClientID
) myview
LEFT OUTER JOIN ContractDetails
on myview.ClientID = ContractDetails.ClientID
WHERE myview.ContractEndDate > '2009-06-30'
ORDER BY ClientID
Le point de cette requête est de trouver tous les clients en direct comme à un moment donné dans le temps, où aucune donnée d'état historique est conservé (à savoir le calcul de la date de fin de contrat d'une date de début du contrat connu et durée).
Quelqu'un peut-il trouver un moyen d'éliminer cette répétition?
suivi final
Robin Day m'a aidé avec la chose clé que je manquais ici qui m'a permis en fait de supprimer la duplication. Cependant KM a un point où il dit que le WHERE devrait être sur la vue imbriquée, plutôt que sur le résultat final, ce qui exigerait qu'une partie de la déclaration soit dupliquée (ce que j'essaie d'éviter). Dans ce cas particulier je peux m'en tirer parce que je sais pas il n'y a pas des millions d'enregistrements dans la table ContractDetails, et ne le sera jamais.
SELECT ClientID,
Name,
ContractStartDate,
myview.ContractLength,
ContractEndDate
FROM (
SELECT ClientID,
Name,
ContractStartDate,
DATEADD(MONTH, ContractDetails.ContractLength, ContractStartdate)
AS ContractEndDate,
ContractDetails.ContractLength as Length
FROM Clients
LEFT OUTER JOIN ContractDetails
on Clients.ClientID = ContractDetails.ClientID
) myview
WHERE myview.ContractEndDate > '2009-06-30'
ORDER BY ClientID
Pourquoi le downvote? – tomfanning
Ajoutez ContractLength à la vue imbriquée et vous n'avez plus besoin d'effectuer la jointure en dehors de cette vue. –