UFO ET IT

WHERE 절의 참조 별칭(SELECT로 계산됨)

ufoet 2023. 4. 8. 14:22
반응형

WHERE 절의 참조 별칭(SELECT로 계산됨)

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

계산된 값BalanceDue선택한 열 목록에서 변수로 설정된 것은WHERE절을 클릭합니다.

할 수 있는 방법이 있을까요? 관련 질문(Where Clause의 MySQL Select Statement 변수 사용)에서는 실제로는 계산을 두 번( 쿼리에서 해당 계산을 수행)만 하면 되는 것처럼 보이지만, 어느 것도 만족스럽지 않습니다.

SELECT는 평가되는 두 번째 마지막 절이기 때문에 ORDER BY를 제외하고 별칭을 참조할 수 없습니다.2가지 회피책:

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

또는 다음 식을 반복합니다.

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

나는 후자가 더 좋다.식이 매우 복잡한 경우(또는 계산 비용이 많이 드는 경우), 특히 많은 쿼리가 동일한 식을 참조하는 경우 계산 열을 고려해야 합니다.

PS 당신의 두려움은 근거가 없는 것 같습니다.이 간단한 예에서는 적어도 SQL Server는 두 번 참조하더라도 계산을 한 번만 수행할 수 있을 정도로 스마트합니다.어서 설계도를 비교해 보세요. 그것들이 똑같다는 것을 알게 될 거예요.표현이 여러 번 평가되는 더 복잡한 케이스가 있는 경우, 더 복잡한 쿼리와 계획을 게시해 주십시오.

다음은 모두 동일한 실행 계획을 생성하는 5가지 쿼리 예입니다.

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;

5가지 쿼리 모두에 대한 결과 계획:

여기에 이미지 설명 입력

다음을 사용하여 이 작업을 수행할 수 있습니다.cross apply

SELECT c.BalanceDue AS BalanceDue
FROM Invoices
cross apply (select (InvoiceTotal - PaymentTotal - CreditTotal) as BalanceDue) as c
WHERE  c.BalanceDue  > 0;

SELECT, WHERE 및 기타 절 모두에서 사용할 수 있는 변수를 효과적으로 정의할 수 있습니다.

크로스 조인은 참조된 테이블 열에 대한 적절한 바인딩을 반드시 허용하는 것은 아니지만, OUTER APPLY에서는 null을 보다 투명하게 처리합니다.

SELECT
    vars.BalanceDue
FROM
    Entity e
OUTER APPLY (
    SELECT
        -- variables   
        BalanceDue = e.EntityTypeId,
        Variable2 = ...some..long..complex..expression..etc...
    ) vars
WHERE
    vars.BalanceDue > 0

시드 메흐로즈 알람에게 경의를 표합니다.

WHERE 구 앞에 SELECT 구를 강제로 평가하기 위한 회피책으로 서브쿼리가 메인쿼리에 남아 있는 동안 서브쿼리를 서브쿼리에 넣을 수 있습니다.

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

심플한 어프로치

SELECT *  FROM Invoices GROUP BY id
HAVING(InvoiceTotal - PaymentTotal - CreditTotal) > 0

언급URL : https://stackoverflow.com/questions/11182339/reference-alias-calculated-in-select-in-where-clause

반응형