2

開始日が現在の日付より前 (<=) で、to_date が現在の日付より後 (>) の場合にメッセージを表示するクエリを実行しています。

to_dateがの場合、メソッドをNULL使用して値を与えNVL、チェック n を 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' の場合、結果を取得しません。つまり、where 句の a.to_date > 現在の条件に失敗するため、これらのエントリは返されません。to_date が NULL の場合、値は '9999-12 ...' で正しく置換されますが、where 条件 '> current' は失敗します。

別のステートメントとしてではなく、クエリ内で置換を行いたいです。論理的にはうまくいくと思いますが、何らかの理由でどこかで間違っています。また、これがクエリの実行に影響するかどうかはわかりませんが、テーブルの作成時に to_date のデフォルト値が NULL に設定されます。

この問題について教えてください。ありがとう

4

3 に答える 3

2

NULL 値の比較について読む必要があります - http://www.w3schools.com/sql/sql_null_values.asp

NULL および 'SOME_DATE' は、=、<、または <> 演算子と比較できません。これらの演算子との比較は常に false になります。

したがって、条件「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 値を排除しているため、出力に NULL 値が存在しないため、 SELECT 句の NVL() 置換は実際には冗長です。

于 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 式の繰り返しが回避されます。

todateAS とto_dateWHEREの間で競合が発生したことに注意してください。また、クエリが複数のテーブルを使用する場合は、各列がどのテーブルに由来するかを特定することをお勧めします (内側のクエリはそうですが、外側のクエリはそうではありません)。通常、テーブルには 1 文字のエイリアスを使用します。今回は、指定されたテーブル名が 1 文字の名前だったため、エイリアスは不要でした。

このクエリ プランは、単一レベル クエリの場合と同じである可能性があります。もちろん、SET EXPLAIN を使用して確認することもできます。

于 2013-02-26T20:16:24.293 に答える