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

Posted

技术标签:

【中文标题】MySQL - 从两列中选择不同的值【英文标题】:MySQL - select distinct value from two column 【发布时间】:2021-03-30 20:10:48 【问题描述】:

我有一个结构如下的表:

IdM|IdS
-------
 1 | 2
 1 | 3
 1 | 4
 2 | 1
 2 | 3
 2 | 4
 3 | 1
 3 | 2
 3 | 3
 3 | 4

我怎样才能在这个表上做一个select语句,它会返回这个表的一些行,在每一行中,一个特定的id只出现一个,与它指定的哪一列无关?

对于上述结果集,我想要一个返回的查询:

-------
 1 | 2
 3 | 4
-------

再举一个例子,如果你想省略原始数据集中的第一行:

IdM|IdS
-------
 1 | 3
 1 | 4
 2 | 1
 2 | 3
 2 | 4
 3 | 1
 3 | 2
 3 | 3
 3 | 4

结果集应该是:

-------
 1 | 3
 2 | 4
-------

【问题讨论】:

【参考方案1】:

这实际上是一个有趣的问题。如果我正确地跟随你,你想遍历数据集并只保留两个值以前从未见过的行。您可以使用递归查询:

with recursive 
    data as (
        select idm, ids, row_number() over(order by idm, ids) rn 
        from mytable 
        where idm <> ids
    ),
    cte as (
        select idm, ids, rn, 1 as to_keep , concat(idm, ',', ids) visited from data where rn = 1
        union all
        select d.idm, d.ids, d.rn,
            (not find_in_set(d.idm, c.visited) and not find_in_set(d.ids, c.visited)),
            case when (not find_in_set(d.idm, c.visited) and not find_in_set(d.ids, c.visited))
                then concat_ws(',', c.visited, d.idm, d.ids)
                else c.visited
            end
        from cte c
        inner join data d on d.rn = c.rn + 1
    )
select idm, ids from cte where to_keep

第一个 CTE 枚举按两列排序的行。然后递归查询遍历结果集,检查两个值是否都是新的,并相应地设置列的标志。标记的数字被保留以用于在接下来的迭代中进行过滤。

Demo on DB Fiddle

请注意,根据您的要求,并非所有值都可能出现在结果集中。考虑以下数据集:

 idm   ids
+-----+---
 1     2
 1     3
 1     4

您的逻辑只会返回第一行。

【讨论】:

这对我来说不是问题,实际上,这是想要的结果。我想用它来对表中可能的条目提出建议,这些条目是相似的,可以合并在一起。由于我的表逻辑只允许将两个单独的行合并为一个(通过创建一个新行,并将前两行版本作为别名提供),这正是所需的行为,如果 id 1 有可能匹配所有其他三个身份证。在管理员手动执行合并或忽略它后,将添加新的 id 对或匹配另一对。谢谢你的回答!:)

以上是关于MySQL - 从两列中选择不同的值的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL:从两列中选择最高的ID并排序

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

SQL查询从两列中检索两个日期之间的数据

尝试从两列中提取多条记录时,精确提取返回的行数超过了请求的行数

sql 从两列PHP MySql中查找排名

MySQL 从两列按值排序