Nie możesz odwoływać się do aliasu, z wyjątkiem ORDER BY, ponieważ SELECT jest przedostatnią klauzulą, która jest oceniana. Dwa obejścia:
SELECT BalanceDue FROM (
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
) AS x
WHERE BalanceDue > 0;
Lub po prostu powtórz wyrażenie:
SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
WHERE (InvoiceTotal - PaymentTotal - CreditTotal) > 0;
Wolę to drugie. Jeśli wyrażenie jest niezwykle złożone (lub kosztowne w obliczeniu), prawdopodobnie powinieneś rozważyć zamiast tego kolumnę obliczaną (i być może utrwaloną), zwłaszcza jeśli wiele zapytań odnosi się do tego samego wyrażenia.
PS Twoje obawy wydają się bezpodstawne. Przynajmniej w tym prostym przykładzie SQL Server jest na tyle inteligentny, że wykonuje obliczenia tylko raz, nawet jeśli odwołałeś się do niego dwukrotnie. Śmiało i porównaj plany; zobaczysz, że są identyczne. Jeśli masz bardziej złożony przypadek, w którym wyrażenie zostało ocenione wielokrotnie, opublikuj bardziej złożone zapytanie i plany.
Oto 5 przykładowych zapytań, które dają dokładnie ten sam plan wykonania:
SELECT LEN(name) + column_id AS x
FROM sys.all_columns
WHERE LEN(name) + column_id > 30;
SELECT x FROM (
SELECT LEN(name) + column_id AS x
FROM sys.all_columns
) AS x
WHERE x > 30;
SELECT LEN(name) + column_id AS x
FROM sys.all_columns
WHERE column_id + LEN(name) > 30;
SELECT name, column_id, x FROM (
SELECT name, column_id, LEN(name) + column_id AS x
FROM sys.all_columns
) AS x
WHERE x > 30;
SELECT name, column_id, x FROM (
SELECT name, column_id, LEN(name) + column_id AS x
FROM sys.all_columns
) AS x
WHERE LEN(name) + column_id > 30;
Wynikowy plan dla wszystkich pięciu zapytań:
MERGE
, upewnij się, że wziąłeś to wszystko pod uwagę:MERGE
z ostrożnością .Możesz to zrobić za pomocą
cross apply
SELECT c.BalanceDue AS BalanceDue FROM Invoices cross apply (select (InvoiceTotal - PaymentTotal - CreditTotal) as BalanceDue) as c WHERE c.BalanceDue > 0;
źródło
W rzeczywistości możliwe jest efektywne zdefiniowanie zmiennej, która może być używana zarówno w klauzulach SELECT, WHERE, jak i innych.
Sprzężenie krzyżowe niekoniecznie pozwala na odpowiednie powiązanie z kolumnami tabeli, do których się odwołuje, jednak OUTER APPLY tak - i traktuje wartości null w bardziej przejrzysty sposób.
SELECT vars.BalanceDue FROM Entity e OUTER APPLY ( SELECT -- variables BalanceDue = e.EntityTypeId, Variable2 = ...some..long..complex..expression..etc... ) vars WHERE vars.BalanceDue > 0
Kudos dla Syed Mehroz Alam .
źródło