sql >> Databáze >  >> RDS >> Sqlserver

Referenční alias (vypočítaný v SELECT) v klauzuli WHERE

Na alias nemůžete odkazovat jinak než v ORDER BY, protože SELECT je předposlední vyhodnocená klauzule. Dvě řešení:

SELECT BalanceDue FROM (
  SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
  FROM Invoices
) AS x
WHERE BalanceDue > 0;

Nebo jen zopakujte výraz:

SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
WHERE  (InvoiceTotal - PaymentTotal - CreditTotal)  > 0;

Dávám přednost tomu druhému. Pokud je výraz extrémně složitý (nebo nákladný na výpočet), měli byste místo něj pravděpodobně zvážit vypočítaný sloupec (a možná trvalý), zvláště pokud mnoho dotazů odkazuje na stejný výraz.

PS, vaše obavy se zdají neopodstatněné. Alespoň v tomto jednoduchém příkladu je SQL Server dostatečně chytrý na to, aby provedl výpočet pouze jednou, i když jste na něj odkazovali dvakrát. Pokračujte a porovnejte plány; uvidíte, že jsou totožné. Pokud máte složitější případ, kdy vidíte výraz vyhodnocovaný vícekrát, zveřejněte prosím složitější dotaz a plány.

Zde je 5 příkladů dotazů, které všechny poskytují přesně stejný plán provádění:

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;

Výsledný plán pro všech pět dotazů:



  1. jak vložit aktuální datum do pole DATE ve formátu dd/mm/rrrr v oracle

  2. Místnost pro Android – Jak vymazat sqlite_sequence pro všechny tabulky

  3. Jak zkontrolovat, zda existuje trigger v PostgreSQL?

  4. Rozdíl v MySQL JOIN a LEFT JOIN