简体   繁体   English

在MINUS查询中指定列会产生与使用*不同的结果

[英]Specifying columns in MINUS query yields different results from using *

When I am executing 当我执行

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

I get expected result of SKIP 10 TAKE 10 (ten rows) 我得到了SKIP 10 TAKE 10的预期结果(十行)

but if I specify columns explicitly 但是如果我明确指定列

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

I get single record back. 我得到单张唱片。 (one row) (一行)

Why does this happen? 为什么会这样? How can I fix this? 我怎样才能解决这个问题?

You are using where rownum < XX without an order by (which would be in a subquery). 您使用的where rownum < XX 而没有 order by (将在子查询中)。

Hence, the returned rows can be any 10 or 20 rows from the table. 因此,返回的行可以是表中的任何10或20行。 In fact, when you run the query multiple times, you might get different results. 实际上,当您多次运行查询时,您可能会得到不同的结果。 This is particularly obvious when you run the query on a parallel system -- whichever thread happens to get data might return it first (although this is not quite so obvious for a simple table scan). 当您在并行系统上运行查询时,这一点尤其明显-碰巧获取数据的任何线程都可能首先返回该查询(尽管对于简单的表扫描而言并不太明显)。

You need something like this: 您需要这样的东西:

(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) ;

Set operations UNION, INTERSECT, MINUS always remove duplicates. 设置操作UNION,INTERSECT,MINUS总是删除重复项。 (UNION has the cousin UNION ALL which does not). (UNION的堂兄UNION ALL却没有)。

There is no way to avoid the removal of duplicates when you use MINUS. 当您使用MINUS时,无法避免删除重复项。 If all you care about are the first three columns (and want to keep duplicates), you need to apply the MINUS operation first, and only then to select the three columns. 如果您只关心前三列(并希望保持重复),则需要首先应用MINUS操作,然后才选择三列。

Like so: 像这样:

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

On further reflection (prompted by Gordon's observation) - while I think this will work (ROWNUM will be the same for the two operands of MINUS), it is not at all clear why MINUS is needed in the first place, either in the original query with select * or in my solution. 经过进一步的思考 (由Gordon的观察提示)-尽管我认为这会起作用(ROWMIN对于MINUS的两个操作数是相同的),但仍然不清楚为什么首先需要MINUS,无论是在原始查询中select *或在我的解决方案中。

The better solution in all cases is to select just once and to use the proper WHERE clause: 在所有情况下,更好的解决方案是只选择一次并使用适当的WHERE子句:

WHERE ROWNUM BETWEEN 11 AND 20

I feel dumb for not having thought about it right away... :-) 我因为没有立即考虑而感到愚蠢... :-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM