FTR calculation using Google Query function

别说谁变了你拦得住时间么 提交于 2021-02-08 11:40:04

问题


I am trying to create crosstabs pivot tables using Google Query function to calculate Employees First Time Resolution (FTR) rate based on the 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   |
+---------+-------+---------+-----------+--------+-------+

OUTPUTS:

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

FORMULA:

=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 |
+---------------------+----------+----------+----------+

FORMULA:

=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% |
+--------------+----------+----------+----------+

FORMULA:

NEED QUERY FORMULA TO CALCULATE FTR AND GENERATE THIS TABLE.

So i plan to club all 3 tables into a single query formula like this once the 3rd table formula is figured out:

={

{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))}

}

The formula in each cell of the 3rd table will be:

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

or simply,

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

Can someone help me generate the 3rd table?


回答1:


Well I found it a bit confusing, but if I've understood correctly, I have an answer that may do what you want. I'm not clear whether you want this all done on the fly, or whether you allow for the intermediate tabale results to appear in your sheet - you referred to tables 1, 2, and 3. I have a formula for the third table, but it is based on two intermediate tables. Possibly the formulas can be combined to eliminate the intermediate tables.

Consider this formula, in H9 on my sample sheet:

={
  {"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),""))}
 }

The first transpose/sort gets the months across the top, the second sort gets the names of all the agents, into column 1, and the arrayformula divides the # of resolutions by the # of opportunities from two intermediate tables, to fill in the FTR values.

Note that I've limited the range of the intermediate tables, but only because of including elements below them for display purposes. These ranges could be made unlimited, like the input data table.

If this is not on the right track, let us know what more you need.

See my sample sheet here. https://docs.google.com/spreadsheets/d/16otcDfnmWMEL0YpgH3aH0vn4Gip6XEY7yPDLQ9Y-83A/edit?usp=sharing




回答2:


An Apps Script solution

Since you already have an answer for the functions, which I believe will get you to the result you want, I want to present an alternative solution for your issue. Besides being far easier (for me) to go with Apps Script, it seems like a much more appropriate tool for these type of jobs.

Though I know there are many that are fans of doing everything with formulas, power to you.

I based the example on the sample spreadsheet given in the answer @kirkg13 gave, as it was much easier to follow than in the question

First, follow this tutorial if you don't know how to create an Apps Script project.

Then fill your data in a sheet like this one:

With the sheet name "InputData". The columns must be the same, though the amount of data is up to you.

Create another sheet called "Report" and leave it blank.

Copy this code into your script editor:

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
}

This will populate the "Report" tab with these dynamic tables.

This is only a framework for you to use as a learning tool, or to adapt to your specific needs.

Reference material for Apps Script

  • Main page
  • Spreadsheet reference


来源:https://stackoverflow.com/questions/64198250/ftr-calculation-using-google-query-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!