简体   繁体   中英

WHERE clause on CASE Statement alias

I have a CASE expression here that is adding a new column IsAccountActive with boolean values. How can I then add a where clause to only query for the rows that are active?

SELECT 
ma.CustomerID,
ma.FirstName,
ma.LastName,
(
    CASE WHEN (
        sa.Active < 1
            OR
        ma.Active < 1
            OR
        (sa.CancelDate IS NOT NULL AND sa.CancelDate <= GETDATE())
            OR
        (ma.CancelDate IS NOT NULL AND ma.CancelDate <= GETDATE())
            OR
        (sa.ExpireDate IS NOT NULL AND DATEADD(dd, sa.Extension + 1, sa.ExpireDate) <= GETDATE())
    ) THEN
        0
    ELSE
        1
    END
) as IsAccountActive
FROM MasterAccounts ma
INNER JOIN SubAccounts sa
ON sa.CustomerID = ma.CustomerID
INNER JOIN MasterAccountData mad
ON mad.CustomerID = sa.CustomerID
WHERE mad.AccountDataTypeID = 20001
AND mad.Data = ''
AND IsAccountActive = 1

WHERE clause does not have any idea about aliased in SELECT list.

Reason: There's a logical processing order in MS SQL server ( see link here ) and in it WHERE is computed before the SELECT list

So one way is to create an inner query and put where outside.

Select * from
(
SELECT 
ma.CustomerID,
ma.FirstName,
ma.LastName,
(
    CASE WHEN (
        sa.Active < 1
            OR
        ma.Active < 1
            OR
        (sa.CancelDate IS NOT NULL AND sa.CancelDate <= GETDATE())
            OR
        (ma.CancelDate IS NOT NULL AND ma.CancelDate <= GETDATE())
            OR
        (sa.ExpireDate IS NOT NULL AND DATEADD(dd, sa.Extension + 1, sa.ExpireDate) <= GETDATE())
    ) THEN
        0
    ELSE
        1
    END
) as IsAccountActive
FROM MasterAccounts ma
INNER JOIN SubAccounts sa
ON sa.CustomerID = ma.CustomerID
INNER JOIN MasterAccountData mad
ON mad.CustomerID = sa.CustomerID
WHERE mad.AccountDataTypeID = 20001
AND mad.Data = '')T
where T.IsAccountActive = 1

Another way is to put case in where clause like

SELECT 
    ma.CustomerID,
    ma.FirstName,
    ma.LastName
    FROM MasterAccounts ma
    INNER JOIN SubAccounts sa
    ON sa.CustomerID = ma.CustomerID
    INNER JOIN MasterAccountData mad
    ON mad.CustomerID = sa.CustomerID
    WHERE mad.AccountDataTypeID = 20001
    AND mad.Data = ''
    AND CASE WHEN (
            sa.Active < 1
                OR
            ma.Active < 1
                OR
            (sa.CancelDate IS NOT NULL AND sa.CancelDate <= GETDATE())
                OR
            (ma.CancelDate IS NOT NULL AND ma.CancelDate <= GETDATE())
                OR
            (sa.ExpireDate IS NOT NULL AND DATEADD(dd, sa.Extension + 1, sa.ExpireDate) <= GETDATE()))
         THEN
            0
        ELSE
            1 
        END =1

Wrap your query up in a derived table (sub-query), then you can apply that condition on its result:

SELECT *
FROM
(
    SELECT 
    ma.CustomerID,
    ma.FirstName,
    ma.LastName,
    (
        CASE WHEN (
            sa.Active < 1
                OR
            ma.Active < 1
                OR
            (sa.CancelDate IS NOT NULL AND sa.CancelDate <= GETDATE())
                OR
            (ma.CancelDate IS NOT NULL AND ma.CancelDate <= GETDATE())
                OR
            (sa.ExpireDate IS NOT NULL AND DATEADD(dd, sa.Extension + 1, sa.ExpireDate) <= GETDATE())
        ) THEN
            0
        ELSE
            1
        END
    ) as IsAccountActive
    FROM MasterAccounts ma
    INNER JOIN SubAccounts sa
    ON sa.CustomerID = ma.CustomerID
    INNER JOIN MasterAccountData mad
    ON mad.CustomerID = sa.CustomerID
    WHERE mad.AccountDataTypeID = 20001
    AND mad.Data = ''
) dt
WHERE IsAccountActive = 1

Note that

(sa.CancelDate IS NOT NULL AND sa.CancelDate <= GETDATE())

can be simplified as

(sa.CancelDate <= GETDATE())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM