SQL:获取连接表的“第一个”项目

问题描述 投票:0回答:4

假设我想显示公司列表,以及该公司的第一位/随机员工。

我可以这样做:

SELECT
  company.id,
  company.name,
  MIN(person.id) AS employee_person_id,
  MIN(person.name) AS employee_person_name
FROM company
LEFT OUTER JOIN person ON (person.company_id = company.id)
GROUP BY company.id;

但我认为使用上面的代码,

MIN(person.id)
MIN(person.name)
可以提供有关两个不同人的信息,对吗?

是否有更好的方法来检索“第一个”(或随机的)员工并显示该人的 ID 和姓名?

sql postgresql left-join greatest-n-per-group
4个回答
2
投票

我会使用

row_number
窗口函数在每个公司内分配一个编号,然后用它来查询第一个人:

SELECT c_id, c_name, p_id, p_name
FROM   (SELECT    c.id AS c_id,
                  c.name AS c_name,
                  p.id AS p_id,
                  p.name AS p_name,
                  ROW_NUMBER() OVER (PARTITION BY c.id ORDER BY p.id ASC) AS rn
        FROM      company c
        LEFT JOIN person p ON p.company_id = c.id) t
WHERE  rn = 1

1
投票

在 Postgres 中,我会推荐

distinct on

SELECT distinct on (c.id)
  c.id,
  c.name,
  p.id AS employee_person_id,
  p.name AS employee_person_name
FROM company c
LEFT OUTER JOIN person p ON p.company_id = c.id
ORDER BY c.id, p.id

对于每家公司,这带来了id最小的人;您可以使用

ORDER BY
子句控制选择哪个人(如果您想要拥有最大 id 的人,您可以使用
ORDER BY c.id, p.id DESC
)。


0
投票

这是获得正确名称的方法:

您必须通过

person.id = s.employee_person_id

将您的结果加入人员表
select s.company_id, s.company_name, s.employee_person_id, p.name as employee_person_name
from person p
inner join (
    SELECT
      company.id as company_id,
      company.name as company_name,
      MIN(person.id) AS employee_person_id
    FROM company
    LEFT OUTER JOIN person ON (person.company_id = company.id)
    GROUP BY company.id
) as s on s.employee_person_id = p.id

0
投票

这是正确的:

MIN(person.id) 和 MIN(person.name) 可以提供关于两个不同人的信息,对吗?

您可以在下面链接的演示中看到这种情况。

GMB

distinct on
通常是最受推荐的选择,但它需要订购,与 Mureinik 的一样。同时,您可以让each公司只需获得any single
person
,而无需先订购:demo

SELECT
  company.id,
  company.name,
  person.id,
  person.name
FROM company LEFT JOIN LATERAL
(SELECT id,name FROM person WHERE company_id=company.id LIMIT 1) person
             ON true;

它是只检索“第一个”(或随机的)员工的便捷方式:它会先找到它,而不必在选择一个之前找到并排序所有可能的匹配项(甚至是快速选择)。每家公司都只是从他们的员工中提取任何一个,这似乎是个主意。

由于没有做额外的工作,速度更快(在 300'000 行样本上为 16'000x) 并且它仅与

company
成比例缩放,几乎忽略了
person
表的大小和增长。

© www.soinside.com 2019 - 2024. All rights reserved.