如何在Google BigQuery中进行转换

Tra*_*sIV 5 python pandas google-bigquery

假设我将以下查询发送到BQ:

SELECT shipmentID, category, quantity
FROM [myDataset.myTable]
Run Code Online (Sandbox Code Playgroud)

此外,假设查询返回如下数据:

shipmentID  category  quantity
1           shoes     5
1           hats      3
2           shirts    1
2           hats      2
3           toys      3
2           books     1
3           shirts    1
Run Code Online (Sandbox Code Playgroud)

如何从BQ中调整结果以产生输出,如下所示:

 shipmentID   shoes  hats  shirts  toys  books
 1            5      3     0       0     0
 2            0      2     1       0     1
 3            0      0     1       3     0
Run Code Online (Sandbox Code Playgroud)

作为一些额外的背景,我实际上有2000多个类别需要转动,数据量是这样的,我不能直接通过Python中的Pandas DataFrame(使用所有内存,然后慢速爬行) .我尝试使用关系数据库,但遇到了列限制,所以我希望能够直接在BQ中执行它,即使我必须通过python构建查询本身.有什么建议?

**编辑1我应该提到,数据本身的旋转可以在块中完成,因此不是问题.真正的麻烦在于之后尝试进行聚合,因此每个shipmentID只有一行.这就是吃掉所有RAM的原因.

**编辑2在尝试下面接受的答案后,我发现尝试使用它来创建2k +列数据透视表导致"资源超出"错误.我的BQ团队能够重构查询以将其分解为更小的块并允许它通过.查询的基本结构如下:

SELECT
  SetA.*,
  SetB.*,
  SetC.*
FROM (
  SELECT
    shipmentID,
    SUM(IF (category="Rocks", qty, 0)),
    SUM(IF (category="Paper", qty, 0)),
    SUM(IF (category="Scissors", qty, 0))
  FROM (
    SELECT
      a.shipmentid shipmentid,
      a.quantity quantity,
      a.category category
    FROM
      [myDataset.myTable] a)
  GROUP EACH BY
    shipmentID ) SetA
INNER JOIN EACH (
  SELECT
    shipmentID,
    SUM(IF (category="Jello Molds", quantity, 0)),
    SUM(IF (category="Torque Wrenches", quantity, 0))
  FROM (
    SELECT
      a.shipmentID shipmentID,
      a.quantity quantity,
      a.category category
    FROM
      [myDataset.myTable] a)
  GROUP EACH BY
    shipmentID ) SetB
ON
  SetA.shipmentid = SetB.shipmentid
INNER JOIN EACH (
  SELECT
    shipmentID,
    SUM(IF (category="Deep Thoughts", qty, 0)),
    SUM(IF (category="Rainbows", qty, 0)),
    SUM(IF (category="Ponies", qty, 0))
  FROM (
    SELECT
      a.shipmentid shipmentid,
      a.quantity quantity,
      a.category category
    FROM
      [myDataset.myTable] a)
  GROUP EACH BY
    shipmentID ) SetC
ON
  SetB.shipmentID = SetC.shipmentID
Run Code Online (Sandbox Code Playgroud)

通过INNER JOIN EACH一个接一个地添加片段,可以无限期地继续上述模式.对于我的应用程序,BQ能够处理每个块大约500列.

Pen*_*m10 5

这是一种方法:

select shipmentID,
  sum(IF (category='shoes', quantity, 0)) AS shoes,
  sum(IF (category='hats', quantity, 0)) AS hats,
  sum(IF (category='shirts', quantity, 0)) AS shirts,
  sum(IF (category='toys', quantity, 0)) AS toys,
  sum(IF (category='books', quantity, 0)) AS books,
from
  (select 1 as shipmentID,           'shoes' as category,    5 as quantity),
  (select 1 as shipmentID,           'hats' as category,      3 as quantity),
  (select 2 as shipmentID,           'shirts' as category,    1 as quantity),
  (select 2 as shipmentID,           'hats' as category,      2 as quantity),
  (select 3 as shipmentID,           'toys' as category,      3 as quantity),
  (select 2 as shipmentID,           'books' as category,     1 as quantity),
  (select 3 as shipmentID,           'shirts' as category,    1 as quantity),
group by shipmentID
Run Code Online (Sandbox Code Playgroud)

返回:

+-----+------------+-------+------+--------+------+-------+---+
| Row | shipmentID | shoes | hats | shirts | toys | books |   |
+-----+------------+-------+------+--------+------+-------+---+
|   1 |          1 |     5 |    3 |      0 |    0 |     0 |   |
|   2 |          2 |     0 |    2 |      1 |    0 |     1 |   |
|   3 |          3 |     0 |    0 |      1 |    3 |     0 |   |
+-----+------------+-------+------+--------+------+-------+---+
Run Code Online (Sandbox Code Playgroud)

有关其他数据透视表示例,请参见手册.