CASE 语句别名上的 WHERE 子句

Mat*_*son 5 sql t-sql sql-server

我这里有一个 CASE 表达式,它添加一个IsAccountActive带有布尔值的新列。那么如何添加一个 where 子句来仅查询活动的行?

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
Run Code Online (Sandbox Code Playgroud)

Dhr*_*shi 4

WHERE 子句不知道 SELECT 列表中的别名。

原因: MS SQL Server 中有一个逻辑处理顺序(请参阅此处的链接),其中 WHERE 在 SELECT 列表之前计算

因此一种方法是创建一个内部查询并将其放在外部。

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
Run Code Online (Sandbox Code Playgroud)

另一种方法是将 case 放在 where 子句中,例如

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
Run Code Online (Sandbox Code Playgroud)