Google 工作表 GROUPBY 将值组合到一个单元格以满足分组列的查询

Google Sheets GROUPBY Query that combines values into one cell to satisfy grouped columns

抱歉,标题令人困惑,我不确定如何最好地描述它。我已附上屏幕截图以进行澄清。请注意,由于涉及敏感信息,我已将第一列删掉。您可以假设第一列中的所有值都相同。 Here's a dummy sheet to work with 我有的是:

我要找的结果如下:

所以很明显,在这种情况下,我手动完成它以显示我正在寻找的结果,但我想要它做的是按 SKU 分组,其中物种、形式和大小相同。这意味着总净重和单位数量列将相加。问题是“日期”列。我希望它显示分组列中的所有日期。我还希望它对“案例类型”和“位置”列执行此操作。

作为参考,这是我一直在使用的查询,没有达到这个结果(它只是删除了日期列)。正如我之前提到的,由于敏感信息,我已经删除了第一列。您可以假定第一列中的所有值都相同:

=QUERY({IMPORTRANGE("MY URL HERE", "'Finalized Inventory'!A3:K")}, "select Col1, Col3, Col4, Col5, Col6, SUM(Col8), Col9, Col10 where Col1<>'' GROUP BY Col1, Col3, Col4, Col5, Col6, Col8, Col9, Col10 label SUM(Col8)''")

我不是特别喜欢这种方法。如果有更好的方法来做到这一点,通过不同的查询或应用程序脚本,我很乐意table使用,那将非常有帮助。

编辑:需要澄清的是,数据经常更新,我正在寻找一种在数据更新时自动更新的解决方案。我需要的基本上正是 Power Sheets“合并和组合”功能的行为,除了我需要它 auto-update 随着数据的变化,Power Sheets 功能创建和静态 table.

解决方案:

您可以使用 Apps 脚本执行以下操作:

  • 使用 getValues().
  • 从源 sheet(在下面的示例中称为 Source)获取数据
  • 得到CustomerSpeciesFormSizeSKU的唯一组合。这将需要从这些行中仅检索这些值,例如使用 map, and then removing all the duplicate arrays from the resulting 2D array (see this answer)。生成的数组(下面示例中的 grups)将包含 CustomerSpeciesFormSizeSKU 的所有唯一组合.
  • 遍历唯一组合,并针对每个组合,使用 filter.
  • 从原始数据中检索与该组合匹配的行(下面示例中的 groupRows
  • groupRows 上使用 reduce 求和 UnitWeight 并添加不同的 DatesCase TypesLocations 到相同的值。
  • 从生成的数组(称为 groupedData)中删除重复的 DatesCase TypesLocations。请参阅 this question 了解如何从数组中删除重复值。
  • 使用 setValues(values), or use return groupedData; instead if you want this to be a custom function.
  • 将数据写入目标 sheet(在下面的示例中称为 Destination

代码片段:

// Copyright 2021 Google LLC.
// SPDX-License-Identifier: Apache-2.0

function myFunction() {
  const ss = SpreadsheetApp.getActive();
  const sourceSheet = ss.getSheetByName("Source");
  const sourceValues = sourceSheet.getRange(3,1,sourceSheet.getLastRow() - 2, sourceSheet.getLastColumn()).getValues(); // Get source data
  const groups = sourceValues.map(row => { // Get unique combinations
    return JSON.stringify([row[0]].concat(row.slice(2,5)).concat(row[8]));
  }).reverse().filter((e, i, a) => a.indexOf(e, i + 1) === -1)
    .reverse().map(JSON.parse);
  let groupedData = groups.map(group => {
    const groupRows = sourceValues.filter(row => { // Get matching rows
      return JSON.stringify([row[0]].concat(row.slice(2,5)).concat(row[8])) === JSON.stringify(group);
    });
    return groupRows.reduce((acc, current) => { // Adding the values from same combination
      const date = acc[1] === "" ? current[1] : acc[1] + "\n" + current[1];
      const caseType = acc[5] === current[5] ? acc[5] : acc[5] + "\n" + String(current[5]);
      const location = acc[11] === "" ? current[11] : acc[11] + "\n" + current[11];
      const unit = Number(acc[6]) + Number(current[6]);
      const weight = Number(acc[7]) + Number(current[7]);
      const comments = acc[10] + "\n" + current[10];
      return [group[0], date, ...group.slice(1,4), caseType, unit, weight, group[4], current[9], comments, location];
    }, Array(12).fill(""));
  });
  groupedData.forEach(row => { // Removing duplicate dates, case types, locations
    row[1] = [...new Set(row[1].split("\n"))].join("\n");
    row[5] = [...new Set(row[5].split("\n"))].join("\n");
    row[11] = [...new Set(row[11].split("\n"))].join("\n");
  });
  return groupedData;
}

输出: