我正在运行查询,以便在起始日期(< =)当前日期之前显示消息,并且to_date在当前日期之后(>)。
如果to_date
是NULL
,那么我使用NVL
方法给它一个值并检查where子句,如果它不是null - 即用户为它提供了值 - 然后它应该使用该值并检查where子句中的条件。
select a.id,
title,
body,
NVL(a.to_date, '9999-12-31 23:59:59') as todate,
cr_date
from a,
b
where a.cust_id = 20 and
a.body_id = b.body_id and
a.from_date <= current and
a.to_date > current
但是当我为我的数据库运行此查询时,我只获得用户输入to_date时的结果。当to_date为null并且其值为'9999-12-31 23:59:59'时,我不会得到结果 - 即: 它失败了a.to_date&gt; where子句中的当前条件,因此不返回这些条目。 to_date为NULL时的值被'9999-12 ...'正确替换,但where条件'&gt;当前'失败。
我想在查询中进行替换而不是单独的语句。从逻辑上讲,我认为它应该可行,但出于某种原因,我在某个地方出错了。还不确定这是否会影响查询执行,但在创建表时,to_date的默认值设置为NULL。
你能帮我解决这个问题。感谢
答案 0 :(得分:2)
您需要阅读NULL值比较 - http://www.w3schools.com/sql/sql_null_values.asp
NULL和'SOME_DATE'无法与=,&lt;或&lt;&gt;进行比较运营商。与这些运算符的比较总是错误的。
因此,您的条件“a.to_date&gt; current”将始终为false,并且永远不会返回任何具有NULL to_date的行。
如果您需要退回,则需要更改查询:
where a.cust_id = 20 and
a.body_id = b.body_id and
a.from_date <= current and
((a.to_date > current) OR (a.to_date IS NULL))
希望这有帮助。
编辑:
根据您的评论,我想澄清一下SQL执行中有一个优先顺序。在这种情况下,将首先评估FROM子句,然后是WHERE,最后是SELECT子句。您在SELECT子句中执行的任何操作仅影响输出的“显示”方式。它不会更改计算的行数。在您的示例中,where子句已经消除了NULL值,因此SELECT子句中的NVL()替换实际上是多余的,因为输出中永远不会有任何NULL值。
答案 1 :(得分:2)
我不是100%明确你的问题,但听起来你希望在WHERE
条款中评估你的替代日期,即使你没有包括NVL()
。你试过这个:
select a.id,
title,
body,
NVL(a.to_date, to_date('9999-12-31 23:59:59', 'YYYY-MM-DD HH24:MI:SS')) as todate,
cr_date
from a,
b
where a.cust_id = 20 and
a.body_id = b.body_id and
a.from_date <= current and
NVL(a.to_date, to_date('9999-12-31 23:59:59', 'YYYY-MM-DD HH24:MI:SS')) > current
答案 2 :(得分:0)
基本问题是'display labels'或'column aliases'不能在查询体(WHERE子句)中使用。你可以使用子查询解决这个问题:
SELECT id, title, body, to_date, cr_date
FROM (SELECT a.id,
a.title,
b.body,
NVL(a.to_date, '9999-12-31 23:59:59') AS to_date,
b.cr_date
FROM a JOIN b ON a.body_id = b.body_id
WHERE a.cust_id = 20
AND a.from_date <= CURRENT
) AS t
WHERE to_date > CURRENT
这可以避免重复NVL表达。
请注意,AS中的todate
与WHERE中的to_date
之间存在冲突。我还建议在查询使用多个表时识别每个列来自哪个表(如内部查询那样,但外部查询没有)。我通常使用单字母别名表;这次,别名是不必要的,因为给出的表名是单字母名称。
此查询计划可能与单级查询相同。当然,您可以使用SET EXPLAIN进行检查。