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
)获取数据
- 得到
Customer
、Species
、Form
、Size
和SKU
的唯一组合。这将需要从这些行中仅检索这些值,例如使用 map, and then removing all the duplicate arrays from the resulting 2D array (see this answer)。生成的数组(下面示例中的 grups
)将包含 Customer
、Species
、Form
、Size
和 SKU
的所有唯一组合.
- 遍历唯一组合,并针对每个组合,使用 filter.
从原始数据中检索与该组合匹配的行(下面示例中的 groupRows
)
- 在
groupRows
上使用 reduce 求和 Unit
、Weight
并添加不同的 Dates
、Case Types
和 Locations
到相同的值。
- 从生成的数组(称为
groupedData
)中删除重复的 Dates
、Case Types
和 Locations
。请参阅 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;
}
输出:
抱歉,标题令人困惑,我不确定如何最好地描述它。我已附上屏幕截图以进行澄清。请注意,由于涉及敏感信息,我已将第一列删掉。您可以假设第一列中的所有值都相同。
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(在下面的示例中称为
- 得到
Customer
、Species
、Form
、Size
和SKU
的唯一组合。这将需要从这些行中仅检索这些值,例如使用 map, and then removing all the duplicate arrays from the resulting 2D array (see this answer)。生成的数组(下面示例中的grups
)将包含Customer
、Species
、Form
、Size
和SKU
的所有唯一组合. - 遍历唯一组合,并针对每个组合,使用 filter. 从原始数据中检索与该组合匹配的行(下面示例中的
- 在
groupRows
上使用 reduce 求和Unit
、Weight
并添加不同的Dates
、Case Types
和Locations
到相同的值。 - 从生成的数组(称为
groupedData
)中删除重复的Dates
、Case Types
和Locations
。请参阅 this question 了解如何从数组中删除重复值。 - 使用 setValues(values), or use
return groupedData;
instead if you want this to be a custom function. 将数据写入目标 sheet(在下面的示例中称为
Source
)获取数据
groupRows
)
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;
}