如何按公司分组结果?

时间:2019-04-29 14:27:15

标签: sql postgresql postgresql-9.6

我有以下sql fiddle

CREATE TABLE companies (pk serial PRIMARY KEY, name text, max int);

INSERT INTO companies(name, max) 
VALUES
  ('Company A', 3),
  ('Company B', 8),
  ('Company C', -1);

CREATE TABLE employees (pk serial PRIMARY KEY, company integer REFERENCES companies (pk), 
                    name text, joined timestamp);

INSERT INTO employees (company, name, joined)
VALUES 
  (2, 'Jane',    '2015-09-23 14:46:57'),
  (2, 'Jack',    '2015-09-23 14:46:57'),
  (3, 'Frank',   '2015-09-23 14:51:07'),
  (2, 'Bob',     '2015-09-23 14:56:11'),
  (1, 'Carl',    '2015-09-23 16:12:05'),
  (1, 'Jason',   '2015-09-23 16:15:35'),
  (3, 'Fred',    '2015-09-23 16:28:35'),
  (2, 'Bruce',   '2015-09-23 16:35:51'),
  (1, 'Brian',   '2015-09-23 16:36:17'),
  (1, 'Ryan',    '2015-09-23 16:36:22'),
  (1, 'Peter',   '2015-09-23 16:37:04'),
  (3, 'Ed',      '2015-09-23 16:37:11'),
  (2, 'Jenny',   '2015-09-23 16:37:15'),
  (2, 'Jessica', '2015-09-24 09:52:46'),
  (3, 'Anita',   '2015-09-24 10:01:19'),
  (3, 'Melanie', '2015-09-24 10:05:27'),
  (3, 'Kathryn', '2015-09-24 10:05:29'),
  (2, 'Ashely',  '2015-09-24 10:19:46'),
  (1, 'Valerie', '2015-09-24 14:49:05'),
  (2, 'Jimmy',   '2015-09-24 15:42:45'),
  (3, 'Johnny',  '2015-09-24 17:38:06'),
  (1, 'Mick',    '2015-09-25 14:49:10');

SELECT *  -- choose the columns you want here
FROM (SELECT e.*, c.max,
             row_number() over (partition by company order by joined desc) as rank
      FROM employees e JOIN
           companies c
           on e.company = c.pk
     ) e
WHERE rank <= max or max = -1

这给出了:

pk  company name    joined  max rank
22  1   Mick    2015-09-25T14:49:10Z    3   1
19  1   Valerie 2015-09-24T14:49:05Z    3   2
11  1   Peter   2015-09-23T16:37:04Z    3   3
20  2   Jimmy   2015-09-24T15:42:45Z    8   1
18  2   Ashely  2015-09-24T10:19:46Z    8   2
14  2   Jessica 2015-09-24T09:52:46Z    8   3
13  2   Jenny   2015-09-23T16:37:15Z    8   4
8   2   Bruce   2015-09-23T16:35:51Z    8   5
4   2   Bob 2015-09-23T14:56:11Z    8   6
1   2   Jane    2015-09-23T14:46:57Z    8   7
2   2   Jack    2015-09-23T14:46:57Z    8   8
21  3   Johnny  2015-09-24T17:38:06Z    -1  1
17  3   Kathryn 2015-09-24T10:05:29Z    -1  2
16  3   Melanie 2015-09-24T10:05:27Z    -1  3
15  3   Anita   2015-09-24T10:01:19Z    -1  4
12  3   Ed  2015-09-23T16:37:11Z    -1  5
7   3   Fred    2015-09-23T16:28:35Z    -1  6
3   3   Frank   2015-09-23T14:51:07Z    -1  7

如何获取结果以便按公司分组结果?例如我想要3行(每个公司1行),然后是每行一组雇员。例如,公司A看起来像:

1 [{"name": "Mick", "joined": "2015-09-25T14:49:10Z", "rank": 1},{"name": "Valerie", "joined": "2015-09-24T14:49:05Z", "rank": 2},{"name": "Peter", "joined": "2015-09-23T16:37:04Z", "rank": 3}]

我一直在尝试各种GROUP BY语句,并在sql无效的地方不断遇到各种错误等。

1 个答案:

答案 0 :(得分:1)

您的示例输出看起来有点像一个JSON数组(但是,这不是有效的JSON值),所以也许您正在寻找这样的东西:

select c.pk, jsonb_agg(to_jsonb(e))
from employees e
  join companies c on e.company = c.pk
group by c.pk;  

要获得三名“最新”员工,您可以使用:

select c.pk, jsonb_agg(e3.emp)
from ( 
  select company, 
         to_jsonb(e) as emp, 
         row_number() over (partition by company order by joined desc) as rn
  from employees e
) e3
  join companies c on e.company = c.pk 
where e3.rn <= 3;

在线示例:https://rextester.com/RPSI96409