您不应该需要 DISTINCT - 您只需要将它放在那里,因为 LEFT JOIN 会导致顾问行重复(每个顾问有多个合同),但您也不需要左连接
SELECT
'The consultant who has led the most contracts is: ' || CONSULTANT_FNAME || ' ' || CONSULTANT_SNAME
FROM CONSULTANT
WHERE CONSULTANT_ID IN(
SELECT CONTRACT_LEAD
FROM CONTRACT
GROUP BY CONTRACT_LEAD
ORDER BY COUNT(CONTRACT_LEAD) DESC
FETCH NEXT 1 ROWS ONLY
)
IN 中的子查询返回最活跃的合同线索 id,但这与顾问 id 相同——您不需要加入。
我相信你也可以这样做:
SELECT
'The consultant who has led the most contracts is: ' || CONSULTANT_FNAME || ' ' || CONSULTANT_SNAME
FROM
CONSULTANT
INNER JOIN CONTRACT ON CONSULTANT_ID = CONTRACT_LEAD
GROUP BY CONSULTANT_FNAME, CONSULTANT_SNAME
ORDER BY COUNT(*) DESC
FETCH NEXT 1 ROWS ONLY
之所以有效,是因为 name 分组实际上与 id 分组相同:它计算合约表导致重复的次数。虽然这有一个轻微的错误风险,但如果真的有两个同名的不同人,他们会将他们的合同添加到一起。为了解决这个问题,您可以将 advisor_id 添加到 group by - 如果您正在执行 group by 则您不能使用 SELECT 区域中未在 group by 中提及的列(除非您将它们放在聚合函数中,例如 min、max等)但您可以将列放在组中,然后您不会在选择中使用。通过添加 ID 我们提供了一种方法来告诉两位同名顾问不要将他们的分数相加:
SELECT
'The consultant who has led the most contracts is: ' || s.CONSULTANT_FNAME || ' ' || s.CONSULTANT_SNAME
FROM
CONSULTANT s
INNER JOIN CONTRACT t ON s.CONSULTANT_ID = t.CONTRACT_LEAD
GROUP BY s.CONSULTANT_FNAME, s.CONSULTANT_SNAME, s.CONSULTANT_ID
ORDER BY COUNT(*) DESC
FETCH NEXT 1 ROWS ONLY
这里是最后的学习点;总是给你的表起别名(我使用了 s 和 t)并使用别名。如果有人将新列添加到例如也称为 CONSULTANT_FNAME 的合同中,这可以防止您的查询停止工作 - 如果没有别名,您的查询将仅在列名明确且数据库架构随时间发生变化时才有效
添加表别名还可以让您将一个表加入两次,这在例如顾问有一个 home_address_id 和一个 work_address_id,它们映射到地址表中的两个不同行。如果您只使用home_address_id = address.id OR work_address_id = address.id 将地址加入一次,那么当数据更适合用作一行时,您最终会得到两行。 sql 101 到此结束 :) 但如果您对此信息块有更多疑问,请参阅When to use SQL Table Alias