简体   繁体   中英

Msg 156, Level 15, State 1, Line 7 Incorrect syntax near the keyword 'BETWEEN'

When I Run This Query

SELECT number, id, clientid, hash, 
    CASE WHEN expirydate IS NULL THEN 
            date 
        ELSE expirydate 
    END as date, 
    CASE company WHEN '' THEN 
            (
                SELECT CONCAT_WS(' ', firstname, lastname) 
                FROM tblcontacts 
                WHERE userid = tblclients.userid 
                and is_primary = 1
            ) 
        ELSE company END as company 

FROM "tblestimates" 
    LEFT JOIN tblclients ON tblclients.userid=tblestimates.clientid
WHERE status != 3 
AND status != 4 
AND CASE WHEN expirydate IS NULL THEN 
        (date BETWEEN '2021-06-27' AND '2021-08-08') 
    ELSE (expirydate BETWEEN '2021-06-27' AND '2021-08-08') 
    END

I Got this Error:

Msg 156, Level 15, State 1, Line 7
Incorrect syntax near the keyword 'BETWEEN'.

Don't use case in where clauses. That is unusual and unneccessary

AND 
(
      (expirydate IS NULL AND [date] BETWEEN '2021-06-27' AND '2021-08-08')
   OR expirydate BETWEEN '2021-06-27' AND '2021-08-08'
)

BTW between is problematic . Better use (note my date changes to 2021-08-09 )

AND 
(
      (expirydate IS NULL AND [date] >= '2021-06-27' AND [date] < '2021-08-09')
   OR expirydate >= '2021-06-27' AND expirydate < '2021-08-09'
)

A CASE statement always resolves to some result value, so logically this would evaluate to either "true" or "false":

CASE
    WHEN expirydate IS NULL THEN 
        (date BETWEEN '2021-06-27' AND '2021-08-08') 
    ELSE
        (expirydate BETWEEN '2021-06-27' AND '2021-08-08') 
END

Unfortunately, SQL Server doesn't have a boolean data type, so you can't use the result of a comparison directly as an expression. Instead, you need to make the CASE statement return a supported type, like a BIT:

CASE 
    WHEN expirydate IS NULL AND date BETWEEN '2021-06-27' AND '2021-08-08'
        THEN 1
    WHEN expirydate IS NOT NULL AND expirydate BETWEEN '2021-06-27' AND '2021-08-08'
        THEN 1
    ELSE 0
END

You can then compare that result to make an expression in your WHERE clause:

WHERE 1 =
    CASE 
        WHEN expirydate IS NULL AND date BETWEEN '2021-06-27' AND '2021-08-08'
            THEN 1
        WHEN expirydate IS NOT NULL AND expirydate BETWEEN '2021-06-27' AND '2021-08-08'
            THEN 1
        ELSE 0
    END

However, that combination can more naturally (and possibly more efficiently) be written with an OR, remembering to put it in brackets if combining it with AND:

WHERE 
  (
     expirydate IS NULL AND date BETWEEN '2021-06-27' AND '2021-08-08'
     OR
     expirydate IS NOT NULL AND expirydate BETWEEN '2021-06-27' AND '2021-08-08'
  )

In this particular case, you can write it even more simply with a COALESCE, because you're comparing whichever column is not null:

WHERE
    COALESCE(expirydate, date) BETWEEN '2021-06-27' AND '2021-08-08'

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