mysql SQL:获取一些列中具有相同值但另一些列中具有唯一值的所有行

wfypjpf4  于 2023-05-16  发布在  Mysql
关注(0)|答案(2)|浏览(112)

我目前正试图找到一种方法来返回所有行,其中至少有一行在任何数量的列中具有相同的值,并且在任何数量的其他列中具有唯一的值。
我想要一个通用的方法来实现这一点,以便能够将其应用于任何场景,在这些场景中,我想要获取所有具有另一行的行具有匹配的id或多个id列,但也具有另一列或其他列的所有不同值的行。
我目前面临的挑战是尝试从许可证数据库中获取行,其中每行都是一个许可证。我想查看多个用户是否有两个相同类型的许可证处于活动状态。因此,我希望获取表示活动许可证的所有行,这些许可证至少有一行具有匹配的电子邮件和许可证类型,但许可证ID不同。这样我就可以知道用户是否为同一类型的许可证被收取两次费用。下面是一个名为Licenses的示例表(假设有一个唯一的主键):
| 身份证|类型|电子邮件|uid|
| --------------|--------------|--------------|--------------|
| 七十六|B|摆锤|十二岁|
| 九十六|C类|摆锤|十二岁|
| 1|一个|摆锤|十一|
| 1|一个|摆锤|十一|
| 三|一个|摆锤|十一|
| 三|一个|摆锤|十二岁|
| 九十|一个|摆锤|十二岁|
| 九九|一个|乔|十四岁|
| 五|B|乔|十五岁|
| 六|B|乔|十五岁|
| 七|B|乔|十六岁|
| 十二岁|一个|拍|二十三|
| 十三|一个|拍|二十三|
| 五十七|一个|伊拉|四十七|
| 五十七|一个|伊拉|四十七|
| 六十|一个|伊安|九九|
这就是我想要的:
| 身份证|类型|电子邮件|uid|
| --------------|--------------|--------------|--------------|
| 1|一个|摆锤|十一|
| 三|一个|摆锤|十一|
| 九十|一个|摆锤|十二岁|
| 五|B|乔|十五岁|
| 六|B|乔|十五岁|
| 七|B|乔|十六岁|
| 十二岁|一个|拍|二十三|
| 十三|一个|拍|二十三|
但是我得到了这个(注意bob的额外行):
| 身份证|类型|电子邮件|uid|
| --------------|--------------|--------------|--------------|
| 1|一个|摆锤|十一|
| 1|一个|摆锤|十一|
| 三|一个|摆锤|十一|
| 三|一个|摆锤|十二岁|
| 九十|一个|摆锤|十二岁|
| 五|B|乔|十五岁|
| 六|B|乔|十五岁|
| 七|B|乔|十六岁|
| 十二岁|一个|拍|二十三|
| 十三|一个|拍|二十三|
因此,伊拉能够被正确地过滤掉,因为ira和类型A的所有记录的ID都是57。但是,bob包含了2个额外的行,因为id与至少一个具有相同电子邮件和类型的其他id不同。如何编写不返回这些重复ID的查询?这是我尝试的查询:

SELECT * FROM Licenses t1
WHERE EXISTS (
    SELECT 1 FROM Licenses t2
    WHERE t1.email = t2.email 
    AND t1.type = t2.type
    AND t1.id <> t2.id
) ORDER BY email;

我如何编写另一个查询,进一步过滤列x,以确保x对于所有条目也是唯一的?
有没有一个通用的方法来处理这样的问题?
谢谢!

3gtaxfhh

3gtaxfhh1#

这应该可以工作:

with dup_licenses as (
    select email, type, id
    from licenses
    group by email, type, id
    having count(1) >1
)
SELECT * FROM Licenses t1
INNER JOIN DUP_LICENSES dl ON
    t1.email = dl.email 
    AND t1.type =dl.type
    AND t1.id = dl.id
) ORDER BY t1.email;

如果要更改定义重复项的列,则只需从CTE SELECT/GROUP BY中添加/删除它们并修改连接条件

zrfyljdw

zrfyljdw2#

尝试以下操作:

select id, type, email, uid 
from
(
  select *,
    min(id) over (partition by type, email) min_id,
    max(id) over (partition by type, email) max_id,
    row_number() over (partition by id, type, email order by uid)  rn -- or maybe order by uid desc
  from tbl_name
) t
where min_id <> max_id -- this is to ensure that there are multiple ids for each (type, email) group
  and rn = 1           -- this is to select only one row for each (id, type, email) group
order by type, email, id

demo

相关问题