降低这个公式的复杂性?

Reduce Complexity of This Formula?

我对优化我一直在 Google 表格中使用的公式有疑问:

=ARRAYFORMULA(
  IF(
    IFERROR(
      MATCH($B2 & A2, ($B:B1) & ($A:A2), 0),
      0
    ) = 0,
    1,
    0))

假设 A 列 (ID) 出现在 B 列(日期)的日期范围内,该公式计算所有唯一值,从而在 C 列(计数)中给出输出。

请注意计数值如何只有 0 和 1,并且仅当 ID 在日期范围内首次出现时才会显示 1。

示例数据如下。

ID  Date    Count
138 Oct-13  1
138 Oct-13  0
29  Oct-13  1
29  Nov-13  1
138 Nov-13  1
138 Nov-13  0

问题是一旦我要解析超过 10000 行,公式就会变得很慢,并且需要一个多小时才能完成计算。我想知道是否有人对如何优化这个公式有什么建议,这样我就不需要 运行 这么久了。

谢谢,

我一直在研究一些公式,我认为这个效果更好,但在 10000 行之后仍然变得很慢。

=IF(COUNTIF((FILTER($A:$A2, $B:$B2 = $B2)),$A2) = 1, 1, 0)

编辑

这是 Google 产品论坛上发布的一个附加公式,它只需放在一个单元格中,并自动填充。这是迄今为止我找到的最佳答案。

=ArrayFormula(IF(LEN(A2:A),--(MATCH(A2:A&B2:B,A2:A&B2:B,0)=ROW(A2:A)-1),))

如果满足某些假设,例如,1. 相同的 ID 号总是一起出现(如果不是,也许您可​​以先按 ID 排序,然后再按日期排序),然后,

=ARRAYFORMULA(1*(A2:A10000&B2:B10000<>A1:A9999&B1:B9999))

如果可以识别日期,我认为您可以使用 + 而不是 & 。同样,在这里和那里做出了各种假设。

我无法找到可以说优于您所拥有的解决方案的纯公式解决方案。然而,我确实提出了一个在线性时间内运行的自定义函数,因此它应该表现良好。我很想知道它与您的最终解决方案相比如何。

/**
 * Returns 1 for rows in the given range that have not yet occurred in the range,
 * or 0 otherwise.
 *
 * @param {A2:B8} range A range of cells
 * @param {2} key_col Relative position of a column to key by, e.g. the sort
 *   column (optional; may improve performance)
 * @return 1 if the values in the row have not yet occurred in the range;
 *   otherwise 0.
 * @customfunction
 */
function COUNT_FIRST_OF_GROUP(range, key_col) {
  if (!Array.isArray(range)) {
    return 1;
  }

  const grouped = {};

  key_col = typeof key_col === 'undefined' ? 0 : key_col - 1; // convert from 1-based to 0-based

  return range.map(function(rowCells) {
    const group = groupFor_(grouped, rowCells, key_col);
    const rowStr = JSON.stringify(rowCells); // a bit of a hack to identify unique rows, but probably a good compromise
    if (rowStr in group) {
      return 0;
    } else {
      group[rowStr] = true;
      return 1;
    }
  });
}

/** @private */
function groupFor_(grouped, row, key_col) {
  if (key_col < 0) {
    return grouped; // no key column; use one big group for all rows
  }

  const key = JSON.stringify(row[key_col]);
  if (!(key in grouped)) {
    grouped[key] = {};
  }
  return grouped[key];
}

要使用它,请在 Google 表格中转到 工具 > 脚本编辑器...,将其粘贴到编辑器中,然后单击保存。然后,在您的电子表格中,使用如下函数:

=COUNT_FIRST_OF_GROUP(A2:B99, 2)

它将自动填充范围内的所有行。你可以 see it in action here.