当我执行时
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
我收回单曲。 (一排)
为什么会这样?我该如何解决这个问题?
答案 0 :(得分: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) ;
答案 1 :(得分:1)
设置操作UNION,INTERSECT,MINUS始终删除重复项。 (UNION有堂兄UNION ALL,但没有)。
使用MINUS时无法避免删除重复项。如果您只关心前三列(并希望保留重复项),则需要先应用MINUS操作,然后才能选择三列。
像这样:
SELECT COL1, COL2, COL3 FROM (
SELECT * FROM TABLE_NAME WHERE ROWNUM <= 20
MINUS
SELECT * FROM TABLE_NAME WHERE ROWNUM <= 10
);
进一步反思(由戈登的观察提示) - 虽然我认为这样可行(对于MINUS的两个操作数,ROWNUM将是相同的),但是为什么需要MINUS并不清楚首先,在select *
的原始查询中或在我的解决方案中。
在所有情况下,更好的解决方案是只选择一次并使用正确的WHERE子句:
WHERE ROWNUM BETWEEN 11 AND 20
我没有立刻想到它,我感到愚蠢......: - )