1

私が実行しているとき

SELECT * FROM TABLE_NAME WHERE ROWNUM <= 20 
MINUS 
SELECT * FROM TABLE_NAME WHERE ROWNUM <= 10 

SKIP10 TAKE10 (10 行)の期待される結果が得られます

しかし、列を明示的に指定すると

SELECT COL1, COL2, COL3 FROM TABLE_NAME WHERE ROWNUM <= 20 
MINUS 
SELECT COL1, COL2, COL3 FROM TABLE_NAME WHERE ROWNUM <= 10

単一のレコードが返されます。(一行)

なぜこれが起こるのですか?どうすればこれを修正できますか?

4

2 に答える 2

1

(サブクエリにある)なしでwhere rownum < XX 使用しています。order by

したがって、返される行は、テーブルの任意の 10 行または 20 行になります。実際、クエリを複数回実行すると、異なる結果が得られる場合があります。これは、並列システムでクエリを実行する場合に特に明白です。たまたまデータを取得したスレッドが最初にデータを返す可能性があります (ただし、単純なテーブル スキャンではそれほど明白ではありません)。

次のようなものが必要です。

(SELECT * FROM (SELECT * FROM TABLE_NAME ORDER BY COL1, COL2, COL3) WHERE ROWNUM <= 20)
MINUS 
(SELECT * FROM (SELECT * FROM TABLE_NAME ORDER BY COL1, COL2, COL3) WHERE ROWNUM <= 10) ;
于 2016-06-30T15:01:22.980 に答える
1

セット演算 UNION、INTERSECT、MINUS は常に重複を削除します。(UNION には従兄弟の UNION ALL がありますが、これはありません)。

MINUS を使用する場合、重複の削除を回避する方法はありません。重要なのは最初の 3 つの列だけであり、重複を保持したい場合は、最初に MINUS 操作を適用してから、3 つの列を選択する必要があります。

そのようです:

SELECT COL1, COL2, COL3 FROM (
    SELECT * FROM TABLE_NAME WHERE ROWNUM <= 20 
    MINUS 
    SELECT * FROM TABLE_NAME WHERE ROWNUM <= 10
);

さらなる考察(ゴードンの観察によって促された) - これはうまくいくと思いますが (ROWNUM は MINUS の 2 つのオペランドで同じになります)、元のクエリのどちらでも、最初に MINUS が必要な理由はまったく明確ではありません。私のソリューションと一緒に、select *または私のソリューションで。

すべてのケースでより良い解決策は、選択を 1 回だけ行い、適切な WHERE 句を使用することです。

WHERE ROWNUM BETWEEN 11 AND 20

すぐに考えなかったのはばかげていると思います... :-)

于 2016-06-30T15:11:39.107 に答える