Расчет FTR с использованием функции запроса Google

#google-sheets #pivot #crosstab #calculated-field #google-query-language

#google-таблицы #сводный #перекрестная таблица #вычисляемое поле #google-query-language

Вопрос:

Я пытаюсь создать перекрестные pivot tables таблицы, используя Google Query function для расчета сотрудников First Time Resolution (FTR) rate на основе number of Issues received while booking Opportunities vs Total Opportunities booked .

  --------- ------- --------- ----------- -------- ------- 
| OppName | OppID | EmpName | MonthYear | Status | Issue |
 ========= ======= ========= =========== ======== ======= 
| abc     | 1000  | alex    | 2020-Jan  | active | yes   |
 --------- ------- --------- ----------- -------- ------- 
| def     | 1001  | alex    | 2020-Jan  | won    | yes   |
 --------- ------- --------- ----------- -------- ------- 
| ghi     | 1002  | alex    | 2020-Feb  | active | no    |
 --------- ------- --------- ----------- -------- ------- 
| jkl     | 1004  | mini    | 2020-Feb  | lost   | yes   |
 --------- ------- --------- ----------- -------- ------- 
| mno     | 1005  | mini    | 2020-Feb  | won    | yes   |
 --------- ------- --------- ----------- -------- ------- 
| pqr     | 1006  | mini    | 2020-Mar  | active | no    |
 --------- ------- --------- ----------- -------- ------- 
| stu     | 1007  | mini    | 2020-Mar  | won    | yes   |
 --------- ------- --------- ----------- -------- ------- 
| vwx     | 1008  | joe     | 2020-Jan  | won    | no    |
 --------- ------- --------- ----------- -------- ------- 
| yza     | 1009  | joe     | 2020-Mar  | lost   | yes   |
 --------- ------- --------- ----------- -------- ------- 
  

ВЫВОДИТ:

 1. NO OF ISSUES:
 -------------- ---------- ---------- ---------- 
| NO OF ISSUES | 2020-Jan | 2020-Feb | 2020-Mar |
 -------------- ---------- ---------- ---------- 
| alex         |        2 |          |          |
 -------------- ---------- ---------- ---------- 
| mini         |          |        1 |        1 |
 -------------- ---------- ---------- ---------- 
| TOTAL        |        2 |        1 |        1 |
 -------------- ---------- ---------- ---------- 
  

ФОРМУЛА:

 =TRANSPOSE(QUERY($A$2:$F,"select D,count(B) WHERE D IS NOT NULL AND E!='lost' AND F = 'yes' Group by D PIVOT C LABEL D 'NO OF ISSUES'",0))
  

 2. TOTAL OPPORTUNITIES:
 --------------------- ---------- ---------- ---------- 
| TOTAL OPPORTUNITIES | 2020-Jan | 2020-Feb | 2020-Mar |
 --------------------- ---------- ---------- ---------- 
| alex                |        2 |        1 |          |
 --------------------- ---------- ---------- ---------- 
| joe                 |        1 |          |          |
 --------------------- ---------- ---------- ---------- 
| mini                |          |        1 |        2 |
 --------------------- ---------- ---------- ---------- 
| TOTAL               |        3 |        2 |        2 |
 --------------------- ---------- ---------- ---------- 
  

ФОРМУЛА:

 =TRANSPOSE(QUERY($A$2:$F,"select D,count(B) WHERE D IS NOT NULL AND E!='lost' Group by D PIVOT C LABEL D 'TOTAL OPPORTUNITIES'",0))
  

 3. FTR%:
 -------------- ---------- ---------- ---------- 
| FTR%         | 2020-Jan | 2020-Feb | 2020-Mar |
 -------------- ---------- ---------- ---------- 
| alex         |          |  100.00% |          |
 -------------- ---------- ---------- ---------- 
| joe          |  100.00% |          |          |
 -------------- ---------- ---------- ---------- 
| mini         |          |          |   50.00% |
 -------------- ---------- ---------- ---------- 
| AVERAGE FTR% |  100.00% |  100.00% |   50.00% |
 -------------- ---------- ---------- ---------- 
  

ФОРМУЛА:

 NEED QUERY FORMULA TO CALCULATE FTR AND GENERATE THIS TABLE.
  

Поэтому я планирую объединить все 3 таблицы в одну формулу запроса, подобную этой, как только будет определена формула 3-й таблицы:

 ={

{TRANSPOSE(QUERY($A$2:$F,"select COUNT(B) WHERE D IS NOT NULL AND E!='lost' AND F = 'yes' Group by D LABEL COUNT(B) 'FTR CALC' FORMAT COUNT(B) ' '",0))};
{TRANSPOSE(QUERY($A$2:$F,"select D,COUNT(B) WHERE D IS NOT NULL AND E!='lost' AND F = 'yes' Group by D PIVOT C LABEL D 'NO OF ISSUES'",0))};
{TRANSPOSE(QUERY($A$2:$F,"select COUNT(B) WHERE D IS NOT NULL AND E!='lost' AND F = 'yes' Group by D LABEL COUNT(B) 'TOTAL'",0))};

{TRANSPOSE(QUERY($A$2:$F,"select COUNT(B) WHERE D IS NOT NULL AND E!='lost' Group by D LABEL COUNT(B) ' ' FORMAT COUNT(B) ' '",0))};
{TRANSPOSE(QUERY($A$2:$F,"select D,COUNT(B) WHERE D IS NOT NULL AND E!='lost' Group by D PIVOT C LABEL D 'TOTAL OPPORTUNITIES'",0))};
{TRANSPOSE(QUERY($A$2:$F,"select COUNT(B) WHERE D IS NOT NULL AND E!='lost' Group by D LABEL COUNT(B) 'TOTAL'",0))}

}
  

Формула в каждой ячейке 3-й таблицы будет:

 =IFERROR(IF(100%-(I2/I7)*100%=0,"",100%-(I2/I7)*100%),"")
  

или просто,

 =100%-(I2/I7)*100%   'above 2 crosstabs starting from column H
  

Может кто-нибудь помочь мне сгенерировать 3-ю таблицу?

Комментарии:

1. Очень жаль, мне трудно понять ваши примеры. Где «джо» по количеству проблем? Сможете ли вы создать образец электронной таблицы Google с ожидаемыми результатами из набора данных? Кроме того, кажется, что вам не нужно публиковать первые две формулы, поскольку они могут не понадобиться для ответа на вопрос, верно? Из того, что я могу сказать, вам нужно создать третью таблицу на основе двух, созданных ранее. Поэтому, пожалуйста, публикуйте только минимальное количество информации. Что такое разрешение в первый раз? Не могли бы вы дать больше контекста / изменить пример на что-то более простое?

2. @iansedano, нет, мне нужны все 3 таблицы. FTR — это в основном no of issues pending in booked opportunities vs total opportunities booked . Джо там нет, no of issues потому что у него может не быть ни pending issues одного для всех его забронированных возможностей.

3. …и причина, по которой я объединяю все 3 таблицы (а также их ИТОГОВЫЕ значения) следующим образом `{ {table1} ; {table2} ; {table3}}, заключается в том, что они могут динамически расширять свои строки, не перекрывая друг друга.

4. Меня смутили ваши уравнения в таблице 3, поскольку я не знал, что находится в столбцах H и I. Поэтому я попытался сделать ответ с нуля, но, возможно, я неправильно понял ваши намерения. Кроме того, есть ли особая причина, по которой вы хотите, чтобы конечная единая формула генерировала все три таблицы плюс их общие строки из одной формулы?

5. @kirkg13 да, мне нужна единая формула, чтобы таблицы были более динамически расположены одна над другой. Мне также нужна строка ИТОГОВ для каждой таблицы, содержащая суммы для столбцов Count и среднее значение для столбца FTR%.

Ответ №1:

Ну, я нашел это немного запутанным, но, если я правильно понял, у меня есть ответ, который может делать то, что вы хотите. Я не совсем понимаю, хотите ли вы, чтобы все это делалось «на лету», или вы допускаете отображение промежуточных результатов табуляции в вашем листе — вы ссылались на таблицы 1, 2 и 3. У меня есть формула для третьей таблицы, но она основана на двух промежуточных таблицах. Возможно, формулы можно объединить, чтобы исключить промежуточные таблицы.

Рассмотрим эту формулу в разделе H9 на моем примере листа:

 ={
  {"FTR%",TRANSPOSE(SORT(UNIQUE(FILTER(D3:D,D3:D<>""))))}; 
  {                 SORT(UNIQUE(FILTER(C3:C,C3:C<>""))),
   ARRAYFORMULA(IFERROR(IF((N3:P5/I3:K5)=0,"",N3:P5/I3:K5),""))}
 }
  

При первом транспонировании / сортировке месяцы отображаются сверху, при второй сортировке имена всех агентов помещаются в столбец 1, а arrayformula делит количество разрешений на количество возможностей из двух промежуточных таблиц, чтобы заполнить значения FTR.

Обратите внимание, что я ограничил диапазон промежуточных таблиц, но только из-за включения элементов под ними для целей отображения. Эти диапазоны можно сделать неограниченными, как и в таблице входных данных.

Если это не на правильном пути, сообщите нам, что вам еще нужно.

Смотрите Мой примерный лист здесь. https://docs.google.com/spreadsheets/d/16otcDfnmWMEL0YpgH3aH0vn4Gip6XEY7yPDLQ9Y-83A/edit?usp=sharing

введите описание изображения здесь

Комментарии:

1. я попытался сложить формулы вашей таблицы одну над другой, но получил ошибку, как видно из вашего Листа1. Чтобы продемонстрировать, я только переставил ваши таблицы одну над другой, оставив пустую строку между каждой таблицей. В таблицах также должна быть строка итогов, как в обычном pivot. Надеюсь, это понятно. Как вы можете видеть, я добавил новую строку с именем emp Mike во входную таблицу. Таким образом, таблицы должны автоматически настраиваться соответствующим образом с обновленными итогами и подсчетами.

2. Дайте мне немного времени. Мне нужно использовать другой подход, поскольку в ваших таблицах 1 и 2 не всегда может быть одинаковое количество агентов или месяцев, как у вас сейчас.

3. Да, это то, что я пытался сказать, когда упоминал Dynamic таблицы. 🙂

4. Поскольку сводная таблица будет рассчитываться по годам и месяцам, есть ли способ показать фиксированное количество 12 месяцев для определенного года, даже если в некоторых месяцах могут не отображаться какие-либо данные? Это делается для того, чтобы избежать ошибки In ARRAY_LITERAL, an Array Literal was missing values for one or more rows из-за несоответствия столбцов между таблицами с накоплением.

Ответ №2:

Решение для скриптов приложений

Поскольку у вас уже есть ответ для функций, который, я полагаю, приведет вас к желаемому результату, я хочу представить альтернативное решение вашей проблемы. Помимо того, что мне намного проще (для меня) использовать Apps Script, он кажется гораздо более подходящим инструментом для такого рода заданий.

Хотя я знаю, что есть много любителей делать все с помощью формул, сила вам.

Я основал пример на образце электронной таблицы, приведенной в ответе @kirkg13, поскольку ему было намного легче следовать, чем в вопросе

Сначала следуйте этому руководству, если вы не знаете, как создать проект скрипта приложений.

Затем заполните свои данные на листе, подобном этому:

введите описание изображения здесь

С именем листа «inputData». Столбцы должны быть одинаковыми, хотя объем данных зависит от вас.

Создайте еще один лист под названием «Отчет» и оставьте его пустым.

Скопируйте этот код в свой редактор сценариев:

 function main() {
  var dataRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("InputData").getDataRange()
  
  var data = dataRange.getValues()
  var headers = data.shift()
  
  var dateRange = getDateRange(data)
  var agentData = buildAgentData(data)
  
  var reportData = buildReport(dateRange, agentData, headers)
  
  SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Report").getRange(1,1,reportData.length, reportData[0].length).setValues(reportData)
}

function getDateRange(data) {
  
  var dates = data.map( (record) => {return record[3]} )
  var minDate = new Date(Math.min.apply(null, dates))
  var maxDate = new Date(Math.max.apply(null, dates))
  
  var counter = minDate
  var dateRange = []
  while (counter <= maxDate) {
    dateRange.push(new Date(counter))
    counter.setDate(counter.getDate()   1);
  }
  return dateRange
}

function buildAgentData(data) {
  
  agentData = {}
  
  data.forEach( (record) => {
    var name = record[2]
    var date = record[3]
    var resolved = record[6]
   
    if (!(name in agentData)) {
      agentData[name] = {[date]:{"cases":1, "resolved":resolved}}
    } else if (date in agentData[name]) {
      agentData[name][date]["cases"]  = 1
      if (resolved == 1) {
        agentData[name][date]["resolved"]  = 1
      }
    } else {
      agentData[name][date] = {"cases":1, "resolved":resolved}
    }
  })
  
  return agentData
}

function buildReport(dateRange, agentData, headers) {
  
  // BUILDING DATA ROWS
  
  var opportunities = [];
  var resolutions = [];
  var ftr = [];
    
  for(agent in agentData) {
    
    var rowOpp = [agent];
    var rowRes = [agent];
    var rowFtr = [agent];
    
    dateRange.forEach( (date) => {
    
      try {rowOpp.push(agentData[agent][date]["cases"])}
        catch(e){rowOpp.push("0")};
      try {rowRes.push(agentData[agent][date]["resolved"])}
        catch(e){rowRes.push("0")};
      try {rowFtr.push(agentData[agent][date]["resolved"] / agentData[agent][date]["cases"])}
        catch(e){rowFtr.push("0")};
    
    });
    
    opportunities.push(rowOpp);
    resolutions.push(rowRes);
    ftr.push(rowFtr);
  }
  
  
  // BUILDING HEADERS
  
  var headerOpp = ["Opportunities"]
  var headerRes = ["Resolutions"]
  var headerFtr = ["FTR"]
  
  dateRange.forEach( (date) => {
                    headerOpp.push("");
                    headerRes.push("");
                    headerFtr.push("");
                    });
  
  dateRange.unshift("");
  
  // BUILDING FINAL REPORT
  
  var report = [dateRange,headerOpp]
  opportunities.forEach((row) => {report.push(row)})
  report.push(headerRes)
  resolutions.forEach((row) => {report.push(row)})
  report.push(headerFtr)
  ftr.forEach((row) => {report.push(row)})
  
  return report
}
  

Вкладка «Отчет» будет заполнена этими динамическими таблицами.

Это всего лишь основа для использования в качестве учебного пособия или для адаптации к вашим конкретным потребностям.

Справочный материал для скрипта приложений

Комментарии:

1. Интересно! Однако maxDate на 1 меньше, чем последняя дата в таблице. например, моей максимальной датой было 1 апреля 2020 года, но она рассчитывается до 31 марта 2020 года. Кроме того, он отображает количество за день, а не группировку за год-месяц. Как это изменить?

2. Здравствуйте, я хотел бы помочь, но я не смогу больше помочь в этом вопросе. Я написал это в качестве примера, чтобы показать вам, чего вы можете достичь с помощью Apps Script, поскольку кажется, что вы сталкиваетесь с ограничениями формул. Эти дополнительные вопросы выходят за рамки исходного вопроса . Лучше всего попробовать и поэкспериментировать с этим кодом, если хотите, и, если вы застряли, задайте другой вопрос. Извиняюсь, что не могу больше помочь.