在 MINUS 查询中指定列会产生与使用 * 不同的结果
Specifying columns in MINUS query yields different results from using *
当我执行
SELECT * FROM TABLE_NAME WHERE ROWNUM <= 20
MINUS
SELECT * FROM TABLE_NAME WHERE ROWNUM <= 10
我得到的预期结果是 SKIP
10 TAKE
10(十行)
但如果我明确指定列
SELECT COL1, COL2, COL3 FROM TABLE_NAME WHERE ROWNUM <= 20
MINUS
SELECT COL1, COL2, COL3 FROM TABLE_NAME WHERE ROWNUM <= 10
我得到了单条记录。 (一行)
为什么会这样?我该如何解决这个问题?
您正在使用 where rownum < XX
没有 order by
(这将在子查询中)。
因此,returned 行可以是 table 中的任意 10 或 20 行。事实上,当您 运行 多次查询时,您可能会得到不同的结果。当您 运行 在并行系统上进行查询时,这一点尤为明显——无论哪个线程碰巧获取数据,都可能首先 return 它(尽管对于简单的 table 扫描而言,这并不是那么明显).
你需要这样的东西:
(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) ;
集合运算 UNION、INTERSECT、MINUS 总是删除重复项。 (UNION 有 UNION ALL 的表亲,而 UNION ALL 没有)。
使用 MINUS 时无法避免删除重复项。如果您只关心前三列(并希望保留重复项),则需要先应用 MINUS 运算,然后才对 select 这三列进行运算。
像这样:
SELECT COL1, COL2, COL3 FROM (
SELECT * FROM TABLE_NAME WHERE ROWNUM <= 20
MINUS
SELECT * FROM TABLE_NAME WHERE ROWNUM <= 10
);
进一步思考(由 Gordon 的观察提示)- 虽然我认为这会起作用(ROWNUM 对于 MINUS 的两个操作数是相同的),但根本行不通清楚为什么首先需要 MINUS,无论是在使用 select *
的原始查询中还是在我的解决方案中。
在所有情况下更好的解决方案是 select 一次并使用正确的 WHERE 子句:
WHERE ROWNUM BETWEEN 11 AND 20
我为没有立即考虑而感到愚蠢...:-)
当我执行
SELECT * FROM TABLE_NAME WHERE ROWNUM <= 20
MINUS
SELECT * FROM TABLE_NAME WHERE ROWNUM <= 10
我得到的预期结果是 SKIP
10 TAKE
10(十行)
但如果我明确指定列
SELECT COL1, COL2, COL3 FROM TABLE_NAME WHERE ROWNUM <= 20
MINUS
SELECT COL1, COL2, COL3 FROM TABLE_NAME WHERE ROWNUM <= 10
我得到了单条记录。 (一行)
为什么会这样?我该如何解决这个问题?
您正在使用 where rownum < XX
没有 order by
(这将在子查询中)。
因此,returned 行可以是 table 中的任意 10 或 20 行。事实上,当您 运行 多次查询时,您可能会得到不同的结果。当您 运行 在并行系统上进行查询时,这一点尤为明显——无论哪个线程碰巧获取数据,都可能首先 return 它(尽管对于简单的 table 扫描而言,这并不是那么明显).
你需要这样的东西:
(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) ;
集合运算 UNION、INTERSECT、MINUS 总是删除重复项。 (UNION 有 UNION ALL 的表亲,而 UNION ALL 没有)。
使用 MINUS 时无法避免删除重复项。如果您只关心前三列(并希望保留重复项),则需要先应用 MINUS 运算,然后才对 select 这三列进行运算。
像这样:
SELECT COL1, COL2, COL3 FROM (
SELECT * FROM TABLE_NAME WHERE ROWNUM <= 20
MINUS
SELECT * FROM TABLE_NAME WHERE ROWNUM <= 10
);
进一步思考(由 Gordon 的观察提示)- 虽然我认为这会起作用(ROWNUM 对于 MINUS 的两个操作数是相同的),但根本行不通清楚为什么首先需要 MINUS,无论是在使用 select *
的原始查询中还是在我的解决方案中。
在所有情况下更好的解决方案是 select 一次并使用正确的 WHERE 子句:
WHERE ROWNUM BETWEEN 11 AND 20
我为没有立即考虑而感到愚蠢...:-)