仅获取列a具有尽可能多的重复条目的行,因为列b中有许多不同的值

时间:2018-03-15 23:41:31

标签: mysql sql

我当前的查询:

select users.id as user_id, opportunities.id as op_id, opportunities.title, certificates.id as cert_id from opportunities
join opportunity_certificates on opportunities.id=opportunity_certificates.opportunity_id
join certificates on opportunity_certificates.certificate_id=certificates.id
join user_certificates on certificates.id=user_certificates.certificate_id
join users on user_certificates.user_id=users.id
where opportunity_certificates.is_required = 1 and
opportunities.id = 1

这将生成下图中的表格。 cert_id列的值可以是1到7,取决于opportunities.id。在下表中,我希望查询只返回具有相同user_id但不同cert_id,1和2的行。

如果表有3个不同的cert_id,我希望它只返回具有相同user_id但不同的cert_id,1,2和3的行。

当cert_id只有一个值时,查询应返回cert_id中具有该值的所有记录。基本上,它应该显示所有需要证书的用户。

查询必须采用当前格式。我试验了

group by users.id
  having count(*) > 

但我不知道如何使该比较动态,相对于cert_id列中的独特值计数。

enter image description here

2 个答案:

答案 0 :(得分:0)

将计数与having条件进行比较。

select u.id as user_id --, o.id as op_id, o.title
from opportunities o
join opportunity_certificates oc on o.id=oc.opportunity_id
join certificates c on oc.certificate_id=c.id
join user_certificates uc on c.id=uc.certificate_id
join users u on uc.user_id=u.id
where oc.is_required = 1 and o.id = 1
group by u.id --,o.id,o.title
having count(distinct c.id)=(select count(distinct id) from certificates)

答案 1 :(得分:0)

有用?

with data as (
    select users.id as user_id, o.title, c.id as cert_id
    from opportunities o
        inner join opportunity_certificates oc on oc.opportunity_id = o.id
        inner join certificates c on c.id = oc.certificate_id
        inner join user_certificates uc on uc.certificate_id = c.id
        inner join users u on u.id = uc.user_id
    where oc.is_required = 1 and o.id = 1
)
select user_id, min(title) as title, max(cert_id) as num_certs
from data
group by user_id
having count(cert_id) = (select max(cert_id) from data);

我假设cert_id值开始,1并按顺序运行。您也可以在count(distinct ...)条款中使用having,但它猜测哪些更明确地表达了您的意图。

如果您的MySQL版本不支持CTE,那么您应该能够将整个子查询放入having子句中。

select u.id as user_id, min(o.title) as title, max(c.cert_id) as num_certs
from opportunities o
    inner join opportunity_certificates oc on oc.opportunity_id = o.id
    inner join certificates c on c.id = oc.certificate_id
    inner join user_certificates uc on uc.certificate_id = c.id
    inner join users u on u.id = uc.user_id
where oc.is_required = 1 and o.id = 1
group by u.id
having count(c.cert_id) = (
    select max(c.cert_id)
    from opportunities o
        inner join opportunity_certificates oc on oc.opportunity_id = o.id
        inner join certificates c on c.id = oc.certificate_id
        inner join user_certificates uc on uc.certificate_id = c.id
        inner join users u on u.id = uc.user_id
    where oc.is_required = 1 and o.id = 1
);

如果你有可用的窗口功能,那么另一个可能有用的。 (它可能更适合Laravel?):

select *
from (
    select users.id as user_id, o.title,
        count(distinct c.id) over (partition by u.id) as user_certs,
        max(c.id) over () as total_certs
    from opportunities o
        inner join opportunity_certificates oc on oc.opportunity_id = o.id
        inner join certificates c on c.id = oc.certificate_id
        inner join user_certificates uc on uc.certificate_id = c.id
        inner join users u on u.id = uc.user_id
    where oc.is_required = 1 and o.id = 1
) t
where user_certs = total_certs;