我的代码示例如下:
我想查找已经开始的合同,并且可能有也可能没有结束日期。如果结束日期晚于今天,或者尚未指定(NULL /空),那么很好。
SELECT
ID, BeginDate, EndDate,
CASE
WHEN EndDate IS NULL
THEN curdate()+1
END as FinishDate
FROM
contracts
WHERE
(id=1) AND
(CURDATE() BETWEEN BeginDate and FinishDate);
但我得到了
#1054 - Unknown column 'FinishDate' in 'where clause
我错过了什么?
答案 0 :(得分:2)
这是因为FinishDate
不是原始表的列,因此其标识符的范围仅限于ORDER BY
子句;它不能在WHERE
子句中使用。
有几种方法可以解决此问题。最简单的方法是将表达式复制到WHERE
子句中:
SELECT
ID, BeginDate, EndDate,
CASE
WHEN EndDate IS NULL
THEN curdate()+1
END as FinishDate
FROM
contracts
WHERE
(id=1) AND
(CURDATE() BETWEEN (CASE WHEN EndDate IS NULL THEN curdate()+1 END) and FinishDate);
注意:大多数RDBMS都有一个特殊的运算符来提供空替换表达式。在MS SQL Server中COALESCE
和ISNULL
:
SELECT
ID, BeginDate, EndDate,
ISNULL(EndDate, curdate()+1) as FinishDate
FROM
contracts
WHERE
(id=1) AND
(CURDATE() BETWEEN ISNULL(EndDate, curdate()+1) and FinishDate);
答案 1 :(得分:0)
在MySQL中,您实际上可以将条件移动到having
子句:
SELECT ID, BeginDate, EndDate,
(CASE WHEN EndDate IS NULL
THEN curdate()+1
END) as FinishDate
FROM contracts
WHERE (id=1)
HAVING (CURDATE() BETWEEN BeginDate and FinishDate);
这是一个MySQL扩展,允许您使用select
中定义的列别名进行过滤。顺便问一下,你确定逻辑是正确的吗?你真的希望它是:
SELECT ID, BeginDate, EndDate, COALESCE(EndDate, curdate() + 1) as FinishDate
不同之处在于,当NULL
有值时,您的版本会将FinishDate
放入EndDate
。如果可用,此版本使用EndDate
,如果不可用,则替换“明天”。