【问题标题】:Specifying columns in MINUS query yields different results from using *在 MINUS 查询中指定列会产生与使用 * 不同的结果
【发布时间】:2016-11-02 18:16:23
【问题描述】:

当我执行时

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

我得到了单条记录。 (一排)

为什么会这样?我该如何解决这个问题?

【问题讨论】:

  • 堆组织的表没有内在的顺序。您的查询没有order by,因此where rownum &lt;= 20 返回任意20 行,rownum &lt;= 10 返回任意10 行。您可以轻松地再次运行相同的查询获得不同的结果。您可能会从执行表扫描的第一个查询和使用索引的第二个查询得到不同的结果,但这只是猜测。如果您想要一组稳定的结果,则需要指定确定性顺序。根据 Oracle 版本,可能还有更简单的构造。
  • 因为您要返回不同的数据,并且您要删除仅包含三列的两组的重复记录。我看不到您的数据,但我假设您的表中有超过三列导致唯一性检查失败。
  • 三列上的结果与所有列上的结果不同,这有什么令人惊讶的?
  • @Siyual Hi Siyual,我也这么认为,如何禁用唯一检查?
  • @MatasVaitkevicius 不做MINUS?你想做什么?

标签: sql oracle skip-take


【解决方案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
);

进一步思考(由 Gordon 的观察提示) - 虽然我认为这会起作用(对于 MINUS 的两个操作数,ROWNUM 将是相同的),但完全不清楚为什么需要 MINUS首先,在使用 select * 的原始查询中或在我的解决方案中。

在所有情况下更好的解决方案是只选择一次并使用正确的 WHERE 子句:

WHERE ROWNUM BETWEEN 11 AND 20

因为没有马上考虑,我感到很愚蠢...... :-)

【讨论】:

  • 这个答案不正确,因为它假定第二个子查询将返回第一个子查询的行子集。这是一个不正确的假设,除非在某些边缘情况下(例如具有 20 行或更少行的表)。
  • @GordonLinoff 我认为这不对。我理解你关于 ROWNUM 不稳定的观点。在这里不质疑 OP 的原因;但是:如果他不关心返回了哪些行,我的查询实际上是正确的,因为一旦外部查询的处理开始,ROWNUM 就已经确定了。也就是说,MINUS 操作的两个操作数中的 ROWNUM 实际上是相同的(即使它们可能在外部查询的不同执行时发生变化)。
【解决方案2】:

您正在使用where rownum &lt; 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) ;

【讨论】:

  • 与排序相同的一条记录,我认为它会像@Siyual 所说的那样删除重复的行。
  • 我了解您在这里通过订购元组来尝试做什么......但这不一定是这里的问题。这是减号命令以及他如何使用它。减号只会返回存在于第一个选择而不是第二个的集合。但是仅使用 3 列并不能为记录带来足够的唯一性。
  • @dvsoukup 。 . .您假设 10 条记录是 20 条记录的子集。这是不正确的假设。此外,OP 没有指定表格有多少列;它可能只有三列。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多