2

I am running a query to display messages when the from date is before (<=) the current date and to_date is after (>) the current date.

If the to_date is NULL, then i give it a value using the NVL method and make the check n the where clause, and if it is not null - ie the user has provided the value for it - then it should use that value and check the condition in the where clause.

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

However when I do run this query for my database, I only get the results for when the user has entered a to_date. I DO NOT get results when to_date is null and it has the value '9999-12-31 23:59:59' - i.e.: It fails the a.to_date > current condition in the where clause and so does not return those entries. The value when to_date is NULL is substituted correctly with '9999-12 ...' but the where condition '> current' fails.

I want to make the substitution within the query and not as a seperate statement. Logically I think it should work but for some reason I am going wrong somewhere . Also not sure if this effects the query execution but the default value of to_date is set to NULL when creating the table.

Can you please help me with this issue. Thanks

4

3 回答 3

2

您需要阅读 NULL 值比较 - http://www.w3schools.com/sql/sql_null_values.asp

NULL 和 'SOME_DATE' 不能与 =、< 或 <> 运算符进行比较。与这些运算符的比较总是错误的。

因此,您的条件“a.to_date > current”将始终为 false,并且永远不会返回任何 to_date 为 NULL 的行。

如果您需要返回它们,您需要更改您的查询:

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 值。

于 2013-02-26T17:56:11.893 回答
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
于 2013-02-26T17:57:14.933 回答
0

基本问题是“显示标签”或“列别名”不可用于查询主体(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 表达式。

todate请注意,您在 AS 和to_dateWHERE中存在冲突。我还建议在查询使用多个表时识别每列来自哪个表(就像内部查询一样,但外部查询没有)。我通常对表格使用单字母别名;这一次,别名是不必要的,因为给定的表名是单字母名称。

对此的查询计划很可能与单级查询相同。当然,您可以使用 SET EXPLAIN 进行检查。

于 2013-02-26T20:16:24.293 回答