Dividing output of one query by another - google-sheets

I am trying to build a tool which tells me the ratio of hours that people of different skillset will be available, as well as which workers are available, for how long and on which days.
This is what I've written so far:
enter image description here
In C2, there is a drop down which allows me to select different locations. The table, then is a pivot and the row at the bottom is a total of this. E.g. ColD is 26+28. I would like to add an additional row which calculates the ratio of 1 worker type to another.
I've tried simply dividing the output of one query by another, as below. On their own, these show a row of values. However, when divided by one another, I just get the value of 0.407, which is the result of dividing the first two columns by one another.
=QUERY(QUERY(Sheet1!$A$1:$M,"select SUM(J)*4 where A like '"&C2&"' and B like '1' pivot D",0), "select * offset 1",0)
/
QUERY(QUERY(Sheet1!$A$1:$M,"select SUM(J)*4 where A like '"&C2&"' pivot D",0), "select * offset 1",0)

I have a suspicion that there might be an easier way of achieving what you want, however it's difficult to know as we can't see the source table for your queries. Having said that, if both your queries resolve to arrays with compatible dimensions (as you've suggested is the case), then wrapping everything in ARRAYFORMULA should give you multiple results which might be what you are looking for, i.e.:
=arrayformula(1st query / 2nd query)

Related

Extract Last Value as Metric from Table Calculation in Tableau?

I have raw data in Tableau that looks like:
Month,Total
2021-08,17
2021-09,34
2021-10,41
2021-11,26
2021-12,6
And by using the following calculation
RUNNING_SUM(
COUNTD(IF [Inserted At]>=[Parameters].[Start Date]
AND [Inserted At]<=[End Date]
THEN [Id] ELSE NULL END
))
/
LOOKUP(RUNNING_SUM(
COUNTD(IF [Inserted At]>=[Parameters].[Start Date]
AND [Inserted At]<=[End Date]
THEN [Id] ELSE NULL END
)),-1)*100-100
I get
Month,My_Calc
2021-08,NULL
2021-09,200
2021-10,80.4
2021-11,28.3
2021-12,5.1
And all I really want is 5.1 (last monthly value) as one big metric (% Month-Over-Month Growth).
How can I accomplish this?
I'm relatively new to Tableau and don't know how to use calculated fields in conjunction with the date groupings aspect to express I want to calculate month-over-month growth. I've tried the native year-over-year growth running total table calculation but that didn't end with the same result since I think my calculation method is different.
First a brief table calc intro, and then the answer at the end.
Most calculations in Tableau are actually performed by the data source (e.g. database server), and the results are then returned to Tableau (i.e. the client) for presentation. This separation of responsibilities allows high performance, even when facing very large data sets.
By contrast, table calculations operate on the table of query results that were returned from the server. They are executed late in the order of operations pipeline. That is why table calcs operate on aggregated data -- i.e. you have to ask for WINDOW_SUM(SUM([Sales)) and not WINDOW_SUM([Sales])
Table calcs give you an opportunity to make final passes of calculations over the query results returned from the data source before presentation to the user. You can for instance calculate a running total or make the visualization layout dynamically depend in part on the contents of the query results. This flexibility comes at a cost, the calculation is only one part of defining a table calc. You also have to specify how to apply the calculation to the table of summary results, known as partitioning and addressing. The Tableau on-line help has a useful definition of partitioning and addressing.
Essentially, table calcs are applied to blocks of summary data at a time, aka vectors or windows. Partitioning is how you tell Tableau how you wish to break up the summary query results into windows for purposes of applying your table calc. Addressing is how you specify the order in which you wish to traverse those partitions. Addressing is important for some table calcs, such as RUNNING_SUM, and unimportant for others, such as WINDOW_SUM.
Besides understanding partitioning and addressing very well, it is also helpful to learn about the functions INDEX(), SIZE(), FIRST(), LAST(), WINDOW_SUM(), LOOKUP() and (eventually) PREVIOUS_VALUE() to really understand table calcs. If you really understand them, you'll be able to implement all of these functions using just two of them as the fundamental ones.
Finally, to partially address your question:
You can use the boolean formula LAST() = 0 to tell if you are at the last value of your partition. If you use that formula as a filter, you can hide all the other values. You'll have to get partitioning and addressing specified correctly. You would essentially be fetching a batch of data from your server, using it in calculations on the client side, but only displaying part of it. This can be a bit brittle depending on which fields are on which shelves, but it can work.
Normally, it is more efficient to use a calculation that can be performed server-side, such as LOD calc, if that allows you to avoid fetching data only for client side calculations. But if the data is already fetched for another purpose, or if the calculation requires table calc features, such as the ability to depend on the order of the values, then table calcs are a good tool.
However you do it, the % month-to-month change from 2021.11 (a value of 26) to the value for 2021.12 (a value of 6) is not 5.1%.
It's (( 6 - 26 ) / 26) * 100 = -76.9 %
OK, starting from scratch, this works for me: ( I don't know how to get exactly the table format I want without using ShowMe and Flip, but it works. Anyone else? )
drag Date to rows, change it to combined Month(Date)
drag sales to column shelf
in showme select TEXT-TABLES
flip rows for columns using tool bar
that gets a table like the one you show above
Drag Sales to color (This is a trick to simply hold it for a minute ),
click the down-arrow on the new SALES pill in the mark card,
select "Add a table calculation",
select Running Total, of SUM, compute using Table(down), but don't close this popup window yet.
click Add Secondary Calculation checkbox at the bottom
select Percent Different From
compute using table down
relative to Previous
Accept your work by closing the popup (x).
NOW, change the new pill in the mark card from color to text
you can see the 5.1% at the bottom. Almost done.
Reformat again by clicking table in ShowMe
and flipping axes.
click the sales column header and hide it
create a new calculated field
label 'rows-from-bottom'
formula = last()
close the popup
drag the new pill rows-from-bottom to the filters shelf
select range 0 to 0
close the popup.
Done.
For the next two weeks you can see the finished workbook here
https://public.tableau.com/app/profile/wade.schuette/viz/month-to-month/hiderows?publish=yes

Adding to a cells value based on two other cells

I'm wondering how I would go about adding to a cell based on two other cells.
For example, I'm creating a Google Sheets document to track profit & loss on certain things in an online game I play.
I'll try to explain this as best as possible.
If cell B71 is equal to the string in cell B7, increase the value in cell D71 equal to the number in cell D7.
However, the values will need to be compared to various other things depending on the item required.
For example, the string in cell B7 might change depending on what specific type of item is needed for that day as it does change daily.
I have cells near the bottom of the sheet which list the different type of item which will show the total amount of items used in that month.
I've tried to explain this a little better as requested below
I'm trying to make a spreadsheet that keeps track of the quantity of a specific item I use in a game for a daily task. This task can be done daily, and to keep track of profit & loss, I have created a spreadsheet to keep track of this.
So, each day, there are three different types of items (runes) that can be used in the machine to create an item called 'Vis Wax'. As Runes are cheap, creating the vis wax can generate a good profit. (I love working with data, hense the spreadsheet.
The image above shows what a daily section looks like. I input each type of rune (has to be 3), input the quantity used and the amount each rune is worth to create the total cost under Total.
Further down below, this table has been created
This will keep track of each rune and the amount used during that month.
So with that said, I'm looking for a solution so that if Air rune is entered in ANY of them slots with the QUANTITY used, it'll update that table accordinly (as well as the other runes that are used too). I've tried nested IF statements, but don't seem to have any luck. With the amount of checks that seem to be happening, I can't seem to find a working solution. As Air Rune might be in slot 1 one day, then slot 3 the next day. So it seems each cell in the Quantity Table will need to compare EACH cell in the daily section, to each rune type that can be used.
Hopefully that has explained it a little better.
Spreadsheet Link
https://docs.google.com/spreadsheets/d/1sYLpZJ46IpNk52gxMoJOIZsOCWToLkC4FF83RBncCf0/edit?usp=sharing
I would suggest you to use a different structure and take all the data from one day in one column, something like this:
In this way you will be able to extend the days keeping the formulas in a really simple way. Below, I will explain some useful formulas that you can use to lighten your work:
Day: =text(DAY(B2),"dddd")
Rune type: Check Data validation to create a drop-down list of your rune types
For counting how many runes have you used you can use SUMIFS function. It returns the sum of a range depending on multiple criteria. In your case, you need apply it three time per rune, as you can have the same rune in three different places. You see it with the following image:
The formula is: =SUMIFS($B$8:$H$8,$B$7:$H$7,A25) + SUMIFS($B$12:$H$12,$B$11:$H$11,A25) + SUMIFS($B$16:$H$16,$B$15:$H$15,A25). In this way you only need to write it once and you can fill the rest of the runes just dragging the mouse. If you need more days just change the column H with the last column that you want to take.
I assume that with all this information you can also keep track of your monthly statics easily. I suggest you to create a different sheet for each month.
I hope that my answer was useful, let me know if you have any doubt.
George, I agree with #fullfine, your data structure does not seem ideal for data analysis. And it doesn't seem that efficient for data entry either, with the sideways scrolling (at least on my screen).
But I recognise that you might not want to change it, perhaps having specific reasons for that layout, and having invested time in it. So I offer this formula as an alternative, which basically pulls the needed cells from your existing sheet, and comes up with the totals you'll need.
=QUERY(QUERY({B7:D9;G7:I9;L7:N9;Q7:S9;V7:X9;AA7:AC9;AF7:AH9;
B20:D22;G20:I22;L20:N22;Q20:S22;V20:X22;AA20:AC22;AF20:AH22;
B33:D35;G33:I35;L33:N35;Q33:S35;V33:X35;AA33:AC35;AF33:AH35;
B46:D48;G46:I48;L46:N48;Q46:S48;V46:X48;AA46:AC48;AF46:AH48;
B59:D61;G59:I61;L59:N61},
"select Col1, Col2, Col3*Col2 where Col1 <>'' order by Col1 label Col3*Col2 '' ",0),
"select Col1, sum(Col2), sum(Col3) group by Col1 label sum(Col2) '', sum(Col3) '' ",0)
The same formula can be used for each month, since it always totals all 31 days, even if the month has fewer days.
For your Rune table in the Statistics sheet, you only need the firsts two columns, so you could delete the "sum(Col3)" from the last select statement.
For your smaller financial table, you would take the sum of the Col3 produced by the above formula, ie. the total value of all the runes used. A similar formula would be used to collect the count of the wax produced, its value, and the profit/loss for each day. This would let you complete the financial table.
If you do decide to go with this approach, and want any help with completing the tables, or the formulas, please share your sheet so "anyone can edit it", to make it easier for me to assist you.

How can I have multiple pivot tables in same sheet?

I have a big sheet with quite a lot of info that keeps growing over time. Based on that, I have created several pivot tables that do some calculations and rankings.
Every ranking keeps growing, so pivot tables may contain 10 rows now, but can grow up to 20 or 30 rows.
I managed to insert several pivot tables in the same sheet and now it looks well, with every ranking after the next one. However, if I add multiple rows, the pivot tables grow and start overlapping, so after a while the ones below start disappearing in favour of the first ones.
Is there a way to have multiple pivot tables in the same sheet with a fixed number of rows among them, preventing them from overlapping?
If you want to 'play' with the data, I created a sample in https://docs.google.com/spreadsheets/d/1MVX3tp6GIqVX6hTyk6TsCxV7YngiMpi7E8oSxa7a9ck/edit?usp=sharing. It is just a ranking on races, where I want to track the best times on different legs. Then it has a second sheet 'rankings' in which I have different pivot tables, one for each leg.
HOw's this for a single formula solution that will scale infinitely in users or legs:
=ARRAYFORMULA(QUERY(SPLIT(FLATTEN(results!A2:A&"|Best of "&results!D1:1&"|"&OFFSET(results!D2,,,ROWS(results!D2:D),COLUMNS(results!D1:1))),"|",0,0),"Select Col2,Col1,MIN(Col3) where Col1<>'' and Col2<>'Best of ' group by Col1,Col2 order by Col2, MIN(Col3) label MIN(Col3)'Best', Col1'User',Col2''"))
You'll find it in cell B1 on the new tab in your sample called MK.Idea
I should mention that FLATTEN() is an undocumented function that I only recently discovered. I've believe it is intended to remain "hidden" in the back end of the sheets programming, but if what I did is what you're after, there really isn't a more efficient way to do it. I've spoken with an engineer at Google who was surprised it existed as well and told me there were no plans to deprecate it, so here's hoping! For a demo of what it does generally, you can see my sample here:
https://docs.google.com/spreadsheets/d/196NDPUZ-p2sPiiiYlYsJeHD6F_eJq7CWO_hP7rFqGpc/edit?usp=sharing
Spreadsheets and Pivot Tables are marvelous tools for data analysis but they aren't too friendly for creating reports and dashboards, if you are open, to recommendations try Google Data Studio (it includes pivot tables too --> https://support.google.com/datastudio/answer/7516660?hl=en)
Let say that you don't have time to learn another app or you just prefer to keep using spreadsheets, in this case it will be required to implement a workaround.
First, bear in mind that Pivot Tables don't actually overlap, instead an error message is shown:
Solution: insert some rows/columns to give enough room to the Pivot Table to be expanded.
NOTE: You could do this in advance by including a "safe zone" (meaning blank rows /columns) around the pivot tables. You could hide/unhide this "safe zone" as needed.
If you don't want to do the above manually, I think that it should be possible to use an on edit trigger of Google Apps Script to detect that pivot tables are shown and insert new rows/columns to avoid this. If the Pivot Table top left cell returns #REF! your script could use a do.. while or a while to insert the required rows or columns. An smart algorithm will read the Pivot Table settings to calculate the required rows and columns and then insert the required rows / columns in one pass.
Related
Pivot table with Google Script

GoogleSheet value search conditioned by approximate match

Hope you're coping with confinement wherever you are.
I'm having some difficulties with a GoogleSheet operation I'd like to do and can't find any suitable solution on the web.
I'm aiming to compare values (decimal numbers) in columns in two separate tables (I'll call table 1 column A and table 2 column C) and obtain the corresponding cell value in another column of the second table (table 2 column E).
Besides, the search is also conditioned by the a corresponding date(month) of the values in both tables (in table 1 column B and table 2 column D).
I've come up to here with a simple INDEX(MATCH()) formula applied in all lines of the table 1 sheet :
=index(table2!A:E;match(A1&month(B1);table2!C:C&month(table2!D:D);0);5)
The twist is that values in A and C are sometimes not exactly the same, they can have a slight difference in decimals, but I still want the match to work. I've tried using STDEV(X;Y)<0,1 inside the INDEX(MATCH()) or a way of using this kind of formula IF(AND(X<=Y+0,1;X>=Y-0,1) but was unsuccessful.
Please let me know if you have any suggestions in doing an efficient search with two conditions with an approximate match for one of them ?
(I have basic knowledge of QUERY functions if this can be done with that too.)
Hope I've been clear enough.
Thanks a lot !
Instead of Roundup and Rounddown, using Round and Abs worked for me.
Not working consistently.
= index($F$2:$H;match(ROUNDDOWN(-$B2;1)&month($A2);ROUNDDOWN($G$2:$G;1)&month($F$2:$F);0);3)
This worked for me. =index($F$2:$H;match(ROUND(abs($B2);1)&month($A2);ROUND($G$2:$G;1)&month($F$2:$F);0);3)
See if this works for your all data. You may need to include if condition if values could be negative/positive in your left table.
Without if condition this also may work -
index($F$4:$H;match(ROUNDup(abs($B4);$B$1)&month($A4);ROUNDup(abs($G$4:$G);$B$1)&month($F$4:$F);0);3)

Sorting a compound range that includes a query

I'm creating a set of process tracking sheets that allows multiple locations to reprioritize their areas by the amount of work left to do in each one, and then feed process updates from those up to a master tracker.
Wondering if there's any way to sort a larger range that includes a query?
Eg, something like:
=sort({query(data, "select *"), D:L}, 2, FALSE)
The idea is that when the amount of remaining work is updated via the query, the entire range A:L sorts as a result. The contents of columns outside the query need to move with the area ID.
Here's an example sheet: https://docs.google.com/spreadsheets/d/1x4f0g38NsKXjCfg-Z4OY9arprefzPE3a6UNMXrbO6H0/edit?usp=sharing
The big restriction here is that these sheets need to involve as little work as possible for the end-user - basically, I want them to update remaining work dynamically and all the end-user has to do is check the Shift boxes.
yes, you can do it but it won't make sense if the query would be ordered because it would shift adjacent columns in havoc so the query formula would need to be static and then sort it as a whole body like:
=QUERY({data!A4:B12, C4:H12}, "order by Col2 desc", 0)
and A4 is:
=ARRAYFORMULA(data!A4:B12)
or directly:
=IMPORTRANGE("ID", "Sheet1!A4:B12")

Resources