ORACLE 仅在某些列中选择不同的值

Posted

技术标签:

【中文标题】ORACLE 仅在某些列中选择不同的值【英文标题】:ORACLE SELECT DISTINCT VALUE ONLY IN SOME COLUMNS 【发布时间】:2021-12-29 12:48:56 【问题描述】:
    +----+------+-------+---------+---------+
    | id | order| value | type    | account | 
    +----+------+-------+---------+---------+
    |  1 | 1    |     a |       2 |    1    |
    |  1 | 2    |     b |       1 |    1    |
    |  1 | 3    |     c |       4 |    1    |
    |  1 | 4    |     d |       2 |    1    |
    |  1 | 5    |     e |       1 |    1    |
    |  1 | 5    |     f |       6 |    1    |
    |  2 | 6    |     g |       1 |    1    |
    +----+------+-------+---------+---------+

我需要选择该表的所有字段,但每个 id+type 组合只能选择 1 行(我不在乎类型的值)。但是我尝试了一些没有结果的方法。

在我创建 DISTINCT 的那一刻,我无法包含其余字段以使其在子查询中可用。如果我在子查询中添加 ROWNUM,所有行都会有所不同,这会导致它不起作用。

一些想法?

目前我更好的查询是:

SELECT ID, TYPE, VALUE, ACCOUNT
FROM MYTABLE
WHERE ROWID IN (SELECT DISTINCT MAX(ROWID)    
                FROM MYTABLE
                GROUP BY ID, TYPE);

【问题讨论】:

请从该输入中显示您需要的确切输出。 您希望每个 idtype 有一行。 value 可以取自任何行。还有account?您只需要帐户 1 吗?或者您实际上想要每个idtypeaccount 一行?或者你想像value一样从行中获取任意account 每个 id 的帐户值始终相同(与值相关)。抱歉隐私,我可以分享真正的价值观,我用通用名称值创建了一个快速简单的例子 您不关心选择了哪一行,但每次运行查询时它是否需要是同一行(确定性)?您是否需要它是不确定的并且每次运行时能够返回不同的行?等等等等? 这能回答你的问题吗? Select First Row of Every Group in sql 【参考方案1】:

您似乎需要为每个不同的 id 和类型组合选择一个(随机)行。如果是这样,您可以使用row_number 分析函数有效地做到这一点。像这样的:

select id, type, value, account
from   (
         select id, type, value, account, 
                row_number() over (partition by id, type order by null) as rn
         from   your_table
       )
where  rn = 1
;

order by null 表示每个组(分区)内的行按(id,type)随机排序;这意味着在这种情况下,通常很耗时的订购步骤将变得微不足道。此外,Oracle 优化了此类查询(针对过滤器 rn = 1)。

或者,在 12.1 及更高版本中,您可以使用 match_recognize 子句获得相同的结果:

select id, type, value, account
from   my_table
match_recognize (
  partition by id, type
  all rows  per match
  pattern   (^r)
  define    r as null is null
);

这会按 id 和类型对行进行分区,它不会对它们进行排序(这意味着随机排序),并且只从每个分区中选择“第一”行。请注意,包括row_number() 在内的一些分析函数需要order by 子句(即使我们不关心排序)-order by null 是习惯性的,但不能完全省略。相比之下,在match_recognize 中,您可以省略order by 子句(默认为“随机顺序”)。另一方面,您不能省略define 子句,即使它没有施加任何条件。为什么 Oracle 也不为该子句使用默认值,只有 Oracle 知道。

【讨论】:

有一个看似独特的列(命名为order,只是为了与关键字发生冲突),然后可以使用它来使这个确定性,尽管仍然是任意的。跨度> @MatBailie - 但是 OP 在他的尝试中明确使用了 ROWID,而不是这个 ORDER 列,这表明他不想重视 ORDER。 我相信那是投影。 OP 说I don't care the value of the type,除此之外,其他一切都是假设。 OP可能想要确定性,可能不关心确定性,可能想要避免确定性;这完全是模棱两可的order 的使用也是如此;不使用它并不表示不想使用它)。因此,我只是将其作为一个选项,而不是一个明确的要求。 我想说的是,我们需要从重复的寄存器中选择一个,不介意类型的值是否为 1,2,3... 只需要每个 id+type 组合中的一个。 在 19c 中他们还引入了any_value 聚合函数,该函数每组返回一个表达式值,这可能更具可读性(但组的随机属性是非常奇怪的要求)。由于“已优化返回第一个值”,因此检查性能会很有趣

以上是关于ORACLE 仅在某些列中选择不同的值的主要内容,如果未能解决你的问题,请参考以下文章

Pyspark - 从每列中选择不同的值

从同一个表的两个不同列中选择不同的值

查询以从与给定值相同的列中选择值,但不同的行

从 SQLITE 中的两列中选择不同的值

MySQL - 从两列中选择不同的值

如何创建临时表或仅从循环中的列中选择不同的值