如何取消嵌套和旋转BigQuery中的两列

时间:2020-09-21 09:02:14

标签: sql google-bigquery

说我有一个包含以下信息的BQ表

| id    | test.name     | test.score    |
|----   |-----------    |------------   |
| 1     | a             | 5             |
|       | b             | 7             |
| 2     | a             | 8             |
|       | c             | 3             |

嵌套测试的位置。我如何将测试转换为下表?

| id    | a     | b     | c     |
|----   |---    |---    |---    |
| 1     | 5     | 7     |       |
| 2     | 8     |       | 3     |

我无法直接进行数据透视测试,因为在pivot(test)处收到以下错误消息:Table-valued function not found。先前的问题(12)不处理嵌套列或已过时。

以下查询看起来是一个有用的第一步:

select a.id, t
from `table` as a,
unnest(test) as t

但是,这只是为我提供了:

| id    | test.name     | test.score    |
|----   |-----------    |------------   |
| 1     | a             | 5             |
| 1     | b             | 7             |
| 2     | a             | 8             |
| 2     | c             | 3             |

3 个答案:

答案 0 :(得分:1)

一个选项可能是使用条件聚合

select id, 
       max(case when test.name='a' then test.score end) as a,
       max(case when test.name='b' then test.score end) as b,
       max(case when test.name='c' then test.score end) as c
from 
(
select a.id, t
from `table` as a,
unnest(test) as t
)A group by id

答案 1 :(得分:0)

有条件的聚合是一个好方法。如果您的桌子很大,您可能会发现它的性能最佳:

select t.id,
       (select max(tt.score) from unnest(t.score) tt where tt.name = 'a') as a,
       (select max(tt.score) from unnest(t.score) tt where tt.name = 'b') as b,
       (select max(tt.score) from unnest(t.score) tt where tt.name = 'c') as c
from `table` t;

我之所以建议这样做是因为它避免了外部聚集。 unnest()的出现没有对数据进行重新排列-我发现这在性能方面是一个巨大的胜利。

答案 2 :(得分:0)

以下是处理案件的通用/动态方式

EXECUTE IMMEDIATE (
  SELECT """
  SELECT id, """ || 
    STRING_AGG("""MAX(IF(name = '""" || name || """', score, NULL)) AS """ || name, ', ') 
  || """
  FROM `project.dataset.table` t, t.test
  GROUP BY id
  """
  FROM (
    SELECT DISTINCT name
    FROM `project.dataset.table` t, t.test
    ORDER BY name
  )
);  

如果要应用于您的问题的样本数据-输出为

Row     id      a       b       c    
1       1       5       7       null     
2       2       8       null    3