【问题标题】:Select 2 unique column in a query在查询中选择 2 个唯一列
【发布时间】:2017-02-14 16:35:56
【问题描述】:

如何构建一个包含两列唯一记录的查询? 这是我尝试的代码:

Select x.a, y.b
from table1 x, table2 y
where x.id = y.id;

1 - a
2 - b
3 - a
4 - b
5 - c
1 - c
6 - a
2 - a
should return this:
1 - a
2 - b
5 - c

但是有数据丢失,没关系,我只想要两个唯一的列。 我曾尝试使用 group by,但这并没有得到两者的独特性。 为了使其对背后的意图更具描述性: 上面的 table1 存储分类,table2 存储值。一个分类可以有多个值,一个值可以属于任意数量的分类。现在我想从 table1 中选择所有(或一些)分类并对应于每个选择一个值,条件是如果与任何其他分类一起选择,则这些值不应重复。在我的示例中,1,2,3..6 是分类,a,b,c 是值。现在我想选择分类和相应的值,我选择了分类 1、2、5 和相应的值 a、b、c,因为所有其他分类都会使值重复(比如 3 会使值重复,因为 a 已经被分类选中1).

【问题讨论】:

  • 是什么让你选择 1-a 而不是 2-a、3-a 和 6-a?
  • 为了使第二个值唯一,您简单地从第一列中忽略了值。因此,如果我们可以随意忽略任何值,那么空的结果集是否适合您?它将不包含重复项。如果这不适合您:您根据什么规则允许或禁止从结果中删除值?
  • 我并不是要你修改任何数据。我只想知道你想应用的规则。如前所述,select null, null from dual where 1=2 已经满足您不选择任何重复项的要求。
  • 我和托尔斯滕一样困惑。还有更多的问题吗?您是否尝试选择满足您的唯一性要求的尽可能多的行(尽可能多的行数)?如果不是,为什么需要选择三行,而不仅仅是前两行,或者最后两行?
  • 不要指望能够轻松解决这个问题,并且要怀疑你自己开发的任何解决方案。您正在寻找的是最大二分匹配,这是图论中的经典难题。有多项式时间算法可以解决它,并且类已经在 J​​ava 等语言中可用。我不知道是否有人用 PL/SQL 编写过它们中的任何一个,而且在纯 SQL 中不太可能有一个相当好的解决方案。

标签: sql database oracle oracle11g


【解决方案1】:

OP 正在寻找具有任意分类 (table1) 的唯一值 (table2)。因此,可以使用的一种方法是从 table2 中枚举每组值中的所有分类和值对,然后仅从每组中选择第一个值。

WITH
    enumerated_data AS
    (
        SELECT 
            ROW_NUMBER() OVER (PARTITION BY y.b ORDER BY x.a DESC) rn
            , x.a
            , y.b
        FROM        table1 x
        INNER JOIN  table2 y ON x.id = y.id
    )
SELECT  a, b
FROM    enumerated_data
WHERE   rn = 1

【讨论】:

  • 考虑为您的答案添加一些解释。没有上下文或解释的原始神秘代码对于要求相似但略有不同的人可能不是很有用。
  • 添加了解释,如果我需要进一步澄清,请告诉我!
  • 这不是简单的select max(a), b from ... group by b 只是写得更复杂吗?
【解决方案2】:

如果您的数据与您在上面发布的一样,那么它已经是唯一的。

1 - a
2 - b
3 - a
4 - b
5 - c
1 - c
6 - a
2 - a

[1,a], [3,a], [6,a], [2,a] 都是独立的唯一值。

如果你想匹配这样的数据,你可以在数字部分使用像 min 或 max 这样的聚合函数。您想要的输出不是最小值或最大值,因此不确定您要达到的目标。

【讨论】:

  • Jonofan,数据是唯一的。但我想改进它,使第 1 列和第 2 列都应该是唯一的。这是我需要 stackoverflow 帮助的唯一原因。其次,存储在这些列中的数据是原始的,不能取最大值/最小值。
  • @uniquephase,你更新的描述更有意义。我可以使用带有 ROW_NUMBER 查询的 CTE 非常接近您想要的输出,但我将 1-a 拉到您想要 5-a 的地方。来自 user1327961 的查询有同样的问题。我认为您可能可以使用递归 CTE 做一些事情,但我无法完全理解它。
  • 我认为@uniquephase提到“5 - c”应该返回是巧合,因为在描述中提到了任意值被列出......我在我的子句中添加了一个order by答案现在将返回“5 - c”,但它以更改其他输出值为代价,因为我包含的 order by desc 子句不会按分类 desc 对其进行排序
  • 啊,好的。如果是这种情况,那么您的查询很好。在我看来,@uniquephase 希望两列都是独一无二的。
【解决方案3】:

听起来需要一个两级分组依据?

select     count(*), x.a, y.b
from       table1 x
inner join table2 y on x.id = y.id
group by   x.a, y.b;

【讨论】:

  • 我试过了。它返回像 1 - a, 2 - b, 5 - c, 3 - a, 4 - b, 2 - a, 1 - c, 6 -a
  • 您确定您尝试过按代码示例中所示的两个级别进行分组吗?两级分组将根据描述为两者提供唯一的设置,这是您想要的。或者,您是说您希望 a 列完全唯一,而 b 列完全唯一?
  • 我希望a列完全唯一,b列完全唯一。
猜你喜欢
  • 1970-01-01
  • 2012-10-15
  • 1970-01-01
  • 1970-01-01
  • 2013-08-30
  • 2021-10-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-24
相关资源
最近更新 更多