SQL根据条件添加到WHERE子句

时间:2017-04-27 02:56:54

标签: sql sql-server database

如何根据案例或条件?

在WHERE CLAUSE中添加条件?
SELECT C.CallID, A.GroupName,A.Assignee, C.CallStatus, C.RecvdDate, C.Urgency, C.Category, C.CallType, C.KPIreport, C.CallDesc,
DATEDIFF(DAY, C.RecvdDate,GETDATE()) [DurationInDays],
CASE 
    WHEN DATEDIFF(DAY, C.RecvdDate,GETDATE()) < 30 
        THEN 'Less than 30'
    WHEN DATEDIFF(DAY, C.RecvdDate,GETDATE()) >= 30 AND DATEDIFF(DAY, C.RecvdDate,GETDATE()) < 60  
        THEN '30-59'
    WHEN DATEDIFF(DAY, C.RecvdDate,GETDATE()) >= 60 AND DATEDIFF(DAY, C.RecvdDate,GETDATE()) < 90  
        THEN '60-89'
    WHEN DATEDIFF(DAY, C.RecvdDate,GETDATE()) >= 90 AND DATEDIFF(DAY, C.RecvdDate,GETDATE()) < 120  
        THEN '90-119'
    WHEN DATEDIFF(DAY, C.RecvdDate,GETDATE()) >= 120 
        THEN 'Over 120'
END 

AS 'AgeClassification'

FROM
    CallLog C
    INNER JOIN Asgnmnt A ON C.CallID = A.CallID
WHERE
    A.HEATSeq =(SELECT MAX(HEATSeq)FROM Asgnmnt WHERE (CallID = C.CallID))
    AND UPPER(A.GroupName) = @GroupName
    AND LOWER(A.EMail) IN (@Assignee)
    AND UPPER(C.CallStatus) = @RecordType

    AND 
    CASE WHEN UPPER(C.CallStatus) = 'CLOSED' THEN
            C.ClosedDate >= @StartDate AND C.ClosedDate <= @EndDate
         WHEN UPPER(C.CallStatus) = 'REQUEST TO CLOSE' THEN
            A.DateResolv >= @StartDate AND A.DateResolv <=@EndDate
    END




ORDER BY A.GroupName, A.Assignee,  C.RecvdDate, C.CallID

我的逻辑是,当@RecordType为'CLOSED'时,WHERE子句必须验证关闭日期,如果@RecordType为'REQUEST TO CLOSE',则它必须验证已解决的日期。< / p>

我也尝试过使用IF语句,但我得到了同样的错误。

3 个答案:

答案 0 :(得分:2)

请尝试以下方法......

SELECT C.CallID,
       A.GroupName,
       A.Assignee,
       C.CallStatus,
       C.RecvdDate,
       C.Urgency,
       C.Category,
       C.CallType,
       C.KPIreport,
       C.CallDesc,
       DATEDIFF( DAY,
                 C.RecvdDate,
                 GETDATE() ) AS DurationInDays,
       CASE
           WHEN DATEDIFF( DAY,
                          C.RecvdDate,
                          GETDATE() ) < 30 THEN
               'Less than 30'
           WHEN DATEDIFF( DAY,
                          C.RecvdDate,
                          GETDATE() ) BETWEEN 30 AND 59
               '30-59'
           WHEN DATEDIFF( DAY,
                          C.RecvdDate,
                          GETDATE() ) BETWEEN 60 AND 89
               '60-89'
           WHEN DATEDIFF( DAY,
                          C.RecvdDate,
                          GETDATE() ) BETWEEN 90 AND 119
               '90-119'
           WHEN DATEDIFF( DAY,
                          C.RecvdDate,
                          GETDATE() ) >= 120 THEN
               '120 or over'
       END AS 'AgeClassification'
FROM
    CallLog C
    INNER JOIN Asgnmnt A ON C.CallID = A.CallID
WHERE
    A.HEATSeq =( SELECT MAX( HEATSeq )
                 FROM Asgnmnt
                 WHERE ( CallID = C.CallID ) )
    AND UPPER( A.GroupName ) = @GroupName
    AND LOWER( A.EMail ) IN ( @Assignee )
    AND UPPER( C.CallStatus ) = @RecordType
    AND ( ( @RecordType = 'CLOSED' AND
            C.ClosedDate BETWEEN @StartDate AND @EndDate ) OR
           ( @RecordType = 'REQUEST TO CLOSE' AND
             A.DateResolv BETWEEN @StartDate AND @EndDate ) OR
           ( @RecordType <> 'CLOSED' AND
             @RecordType <> 'REQUEST TO CLOSE' )
        );

我接受了WHERE条款中的前四个条件。我没有使用CASE作为第五个条件,而是使用ANDOR和圆括号选择等效表单。第一个子条件@RecordType = 'CLOSED' AND C.ClosedDate BETWEEN @StartDate AND @EndDate相当于您的第一个WHEN。第二个子条件@RecordType = 'REQUEST TO CLOSE' AND A.DateResolv BETWEEN @StartDate AND @EndDate )相当于您的第二个WHEN。第三个子条件将允许符合@RecordType既不是CLOSED也不REQUEST TO CLOSE的其他条件的所有记录。如果您希望在这些情况下返回空集,则应删除第三个子条件。

从您的第四个WHERE条件开始,UPPER( C.CallStatus )等于CLOSEDREQUEST TO CLOSE@RecordType也是如此。因此,我已在第五个条件中将UPPER( C.CallStatus )替换为@RecordType。除了稍微更具可读性之外,这还消除了语句中的四个函数调用,使其更有效。

我还从语句的早期修改了你的CASE到等效条件,使用较少的函数调用,(可以说)更容易阅读,并且更清楚地平行你的字段别名。

如果您有任何问题或意见,请随时发表评论。

进一步阅读

"CASE" statement within "WHERE" clause in SQL Server 2008

答案 1 :(得分:1)

SELECT C.CallID, A.GroupName,A.Assignee, C.CallStatus, C.RecvdDate, 
       C.Urgency, C.Category, C.CallType, C.KPIreport, C.CallDesc,
       DATEDIFF(DAY, C.RecvdDate,GETDATE()) [DurationInDays],
       CASE 
          WHEN (DATEDIFF(DAY, C.RecvdDate,GETDATE()) < 30) THEN 'Less than 30'
          WHEN (DATEDIFF(DAY, C.RecvdDate,GETDATE()) >= 30 AND DATEDIFF(DAY, C.RecvdDate,GETDATE()) < 60) THEN '30-59'
          WHEN (DATEDIFF(DAY, C.RecvdDate,GETDATE()) >= 60 AND DATEDIFF(DAY, C.RecvdDate,GETDATE()) < 90) THEN '60-89'
          WHEN (DATEDIFF(DAY, C.RecvdDate,GETDATE()) >= 90 AND DATEDIFF(DAY, C.RecvdDate,GETDATE()) < 120) THEN '90-119'
          WHEN (DATEDIFF(DAY, C.RecvdDate,GETDATE()) >= 120)  THEN 'Over 120'
       END  AS 'AgeClassification'
FROM CallLog C
INNER JOIN Asgnmnt A ON C.CallID = A.CallID
WHERE A.HEATSeq =(SELECT MAX(HEATSeq)FROM Asgnmnt WHERE (CallID = C.CallID))
AND UPPER(A.GroupName) = @GroupName
AND LOWER(A.EMail) IN (@Assignee)
AND UPPER(C.CallStatus) = @RecordType
AND (CASE 
    WHEN UPPER(C.CallStatus) = 'CLOSED' THEN C.ClosedDate
    WHEN UPPER(C.CallStatus) = 'REQUEST TO CLOSE' THEN A.DateResolv
END) BETWEEN @StartDate AND @EndDate
ORDER BY A.GroupName, A.Assignee,  C.RecvdDate, C.CallID

答案 2 :(得分:0)

您可以尝试以下

SELECT C.CallID, 
       A.GroupName, 
       A.Assignee, 
       C.CallStatus, 
       C.RecvdDate, 
       C.Urgency, 
       C.Category, 
       C.CallType, 
       C.KPIreport, 
       C.CallDesc, 
       Datediff(DAY, C.RecvdDate, Getdate()) [DurationInDays], 
       CASE 
         WHEN Datediff(DAY, C.RecvdDate, Getdate()) < 30 THEN 'Less than 30' 
         WHEN Datediff(DAY, C.RecvdDate, Getdate()) >= 30 
              AND Datediff(DAY, C.RecvdDate, Getdate()) < 60 THEN '30-59' 
         WHEN Datediff(DAY, C.RecvdDate, Getdate()) >= 60 
              AND Datediff(DAY, C.RecvdDate, Getdate()) < 90 THEN '60-89' 
         WHEN Datediff(DAY, C.RecvdDate, Getdate()) >= 90 
              AND Datediff(DAY, C.RecvdDate, Getdate()) < 120 THEN '90-119' 
         WHEN Datediff(DAY, C.RecvdDate, Getdate()) >= 120 THEN 'Over 120' 
       END                                   AS 'AgeClassification' 
FROM   CallLog C 
       INNER JOIN Asgnmnt A 
               ON C.CallID = A.CallID 
WHERE  A.HEATSeq = (SELECT Max(HEATSeq) 
                    FROM   Asgnmnt 
                    WHERE  ( CallID = C.CallID )) 
       AND Upper(A.GroupName) = @GroupName 
       AND Lower(A.EMail) IN ( @Assignee ) 
       AND Upper(C.CallStatus) = @RecordType 
       AND C.ClosedDate BETWEEN IIF(Upper(C.CallStatus) = 'CLOSED', @StartDate, C.ClosedDate) 
                        AND IIF(Upper(C.CallStatus) = 'CLOSED', @EndDate, C.ClosedDate) 
       AND C.DateResolv BETWEEN IIF(Upper(C.CallStatus) = 'REQUEST TO CLOSE', @StartDate, C.DateResolv) 
                        AND IIF(Upper(C.CallStatus) = 'REQUEST TO CLOSE',@EndDate, C.DateResolv) 
ORDER  BY A.GroupName, 
          A.Assignee, 
          C.RecvdDate, 
          C.CallID