SELECT 个外键重复的值

SELECT values where their foreign keys are duplicate

假设我们有 clientsproviders。一个客户可以有多个提供商(如互联网、phone、电视等),我想找到拥有多个提供商的客户的名字。

create table clients
(
    client_id char(8) not null,
    client_name varchar(80) not null,
    contract char(1) not null,
    primary key (client_id)
)

create table client_provider
(
    provider_id char(11) not null,
    client_id char(8) not null,
    primary key (provider_id, client_id),
    foreign key (provder_id) references providers ON DELETE CASCADE,
    foreign key (client_id) references clients ON DELETE CASCADE
);

因此,即使对providers一无所知,我们也可以通过以下关系代数来了解拥有多个供应商的客户(刚开始学习,如有错误请指正):

πclient_name (

[ σ client_provider2.provider_id ≠ client_provider.provider_id ∧ client_provider2.client_id = client_provider.client_id (ρ client_provider2 (client_provider) ⨯ client_provider))

⨝ 客户]

到目前为止我尝试了什么(在第 1 行返回 "not a GROUP BY expression"):

SQL> select c.client_name 
  2  from clients c
  3  inner join client_provider cp on c.client_id = cp.client_id
  4  group by cp.client_id
  5  having count(*) > 1;

使用 GROUP BY 时,所有使用的列都应在 GROUP BY 或聚合函数中。要解决此问题,请执行以下操作:

  1. SELECT子句中添加cp.client_id
  2. GROUP BY 子句中添加 c.client_name
SELECT
    cp.client_id,
    c.client_name
FROM clients c
INNER JOIN client_provider cp
    ON c.client_id = cp.client_id
GROUP BY
    cp.client_id,
    c.client_name
HAVING
    COUNT(1) > 1

所有非聚合列都必须在 group by 子句中,现在您知道了。

正如您评论说您只想显示 client_name 而不是 client_id (而它必须在 group by 子句中),使用当前查询作为 source 为最终结果:

select client_name
from (-- current query begins here
      select cp.client_id,
             c.client_name
      from clients c join client_provider cp on c.client_id = cp.client_id
      group by cp.client_id, 
               c.client_name
      having count(*) > 1
      -- current query ends here
     );

或者,您可以使用(稍作修改的)当前查询作为子查询:

select cl.client_name
from client cl
where cl.client_id in (select cp.client_id
                       from client_provider cp
                       group by cp.client_id
                       having count(*) > 1
                      );