如何将多行合并为一个摘要行?

时间:2019-10-18 22:48:01

标签: sql postgresql

我具有以下架构和数据:

create table chips (
  ID serial PRIMARY KEY,
  name VARCHAR (255) NOT NULL
  );

create table test_records (
  chip_id INTEGER,
  some_val VARCHAR (255),
  record INTEGER
  );

insert into chips values 
(1,'chip_1'),
(2,'chip_2');
insert into test_records values
(1,'thumbnail',53),
(1,'first_failure',42),
(1,'another_metric',33),
(2,'thumbnail',54)

然后我尝试运行以下sql:

select * 
FROM 
chips 
INNER JOIN test_records ON test_records.chip_id = chips.id
WHERE 
chips.id = 1

这有效。我在这里摆弄着:https://www.db-fiddle.com/f/qMmJ6UxMfx8Fd87wgAsaBs/0

但是我想做的是

select
chip.id
test_record.thumbnail
test_record.first_failure
FROM 
test_records
INNER JOIN chips ON chips.id = test_record.chips
WHERE 
chips.id = 1

并有一行类似于

的行
(chip_id:1, thumbnail:53,first_failure:42)

这当然不起作用,因为缩略图和first_failure不是列。 我基本上希望它在那些连接的chip_id为1的情况下,在some_val中查找值为缩略图或首次失败的值,并将记录归为结果。

我知道这是开放式的。我什至不知道从哪里开始。这是我需要数据透视表的地方吗?我对这些内容了解不多,但是在查询过程中会创建一个临时表。还是我需要子查询?我在其中选择(查询缩略图记录)AS缩略图,(查询first_failure AS首次失败)。否则会容易得多,而且我会使事情变得过于复杂。

任何标题的改进都将受到欢迎。

3 个答案:

答案 0 :(得分:0)

您似乎正在寻找条件聚合:

select
    c.id,
    max(case when r.some_val  = 'thumbnail' then r.record end) thumbnail,
    max(case when r.some_val  = 'first_failure' then r.record end) first_failure
from 
    chips c
    inner join test_records r on c.id = r.chip_id
group by c.id

Demo on DB Fiddle

| id  | thumbnail | first_failure |
| --- | --------- | ------------- |
| 1   | 53        | 42            |
| 2   | 54        |               |

要根据给定的芯片ID进行过滤,您只需添加一个where子句(它位于group by子句之前)。

答案 1 :(得分:0)

以下内容接近。它返回:

id    value
1     (thumbnail:53, first_failure:42, another_metric:33)

查询为:

select c.id, '(' || string_agg(some_val || ':' || record, ', ') || ')' as value
FROM chips c INNER JOIN
     test_records tr
     ON tr.chip_id = c.id
WHERE c.id = 1
GROUP BY c.id;

Here是db <>小提琴。

很容易将chip_id放入字符串中。我只是不确定那是否是您真正想要的-为什么您不进行一项测量却包含ID?

而且,我想到您可能真的想要JSON。

答案 2 :(得分:0)

我想您将要使用json表示该结果行。您可以使用json functions,特别是aggregate function json_object_agg来构造它:

SELECT chip_id, json_object_agg(some_val, record)
FROM test_records
GROUP BY chip_id

1   { "thumbnail" : 53, "first_failure" : 42, "another_metric" : 33 }
2   { "thumbnail" : 54 }

现在可以在该对象中获得芯片ID甚至更好的名称,我可以想到两种方法。第一个将使用jsonb_set在聚合对象中创建一个新键:

select jsonb_set(jsonb_object_agg(some_val, record), '{chip_name}'::text[], to_jsonb(name))
FROM chips 
INNER JOIN test_records ON test_records.chip_id = chips.id
GROUP BY id

第二个是从一个联合中选择集合:

SELECT json_object_agg(key, value)
FROM (TABLE test_records
  UNION ALL
  SELECT id, 'chip_id', id
  FROM chips) as kv(id, key, value)
GROUP BY id

online demo of all queries

当然,您也可以使用WHERE子句来过滤单个结果,而不是使用上面演示的GROUP BY id。您甚至可以对chip_id键的值进行硬编码:

SELECT json_object_agg(key, value)
FROM (SELECT some_val as key, record as value
  FROM test_records
  WHERE chip_id = 1
  UNION ALL
  VALUES ('chip_id', 1)
) kv

online demo of all approaches