I'm trying to set up a look at YoY based on quarters, thus (Q1 2016 Rev/Q2 2015 Rev) - 1.
My data is in quarters, so I'm trying to set up a calculated field with (Rev at Current Quarter / Rev at (Current Quarter - 4)) - 1
But I'm not sure how to set up that dependency in Tableau.
Thanks for reading
EDIT:
Example of Data
quarter_id | quarter_revenue
10 | 200
11 | 430
12 | 250
13 | 300
14 | 405
15 | 493
16 | 299
So quarter_id 10 corresponds to 2015 Q1, then 11 is 2015 Q2, etc. Currently I can set this into Tableau and use Quick Table Calculation: Percent Difference on Quarter_Revenue which gets me the difference for id 11 and 10 (2015 Q2 and 2015 Q1).
What I want to do is look a year ahead however, and do this calculation 4 quarters ahead. So to compare 2015 Q1 vs 2016 Q1, I would need to do look at id 14 and id 10, and the calculation for Percent Difference would be (405/200)-1.
Related
Using Postgres 11.6, I'm trying to analyze some event data. The goal is to find the durations for all events with a specific name, and then split each one out into evenly sized buckets. We're looking for any times that "clump" for a specific event. I'm editing my question as the specific case may be obscuring what I'm trying to ask.
Simple example
The question is "how do you group rows by a value, then split occurrences by frequency into buckets with count and average for each of those buckets." Here's a hand-done toy example with rounded averages:
Months with values, each number here represents a row.
Jan 12 24 60 150 320 488
Feb 8 16 40 100 220
Mar 4 8 20 310
Overall figures
Month Count Avg Min Max
Jan 6 176 12 488
Feb 5 77 8 220
Mar 4 86 4 310
The same original data, but with more data, including repeated values and a wider range.
Jan 12 12 12 12 24 24 60 60 150 320 488 500
Feb 8 8 8 8 8 16 40 100 220 440 1100
Mar 4 8 8 8 8 20 20 20 20 310
Overall figures
Month Count Avg Min Max
Jan 12 140 12 500
Feb 11 178 8 1100
Mar 10 43 4 310
Mock-up of one of the sets of data split out into 3 buckets
Month Count Avg Min Max Bucket
Jan 4 12 12 12 0
Jan 4 42 24 60 1
Jan 4 365 150 500 2
...and so on for Feb and Mar
I'm just guessing at how the buckets would split in the mock-up above.
That pretty much captures what I'm trying to do. Group by month name (from_to_node in my real case), split the resulting rows into buckets, and then get min, max, avg, and count for each bucket. It's starting to sound like a pivot (?)
Real Table Setup
Here's the structure of table I'm getting a feed for:
CREATE TABLE IF NOT EXISTS data.edge_event (
id uuid,
inv_id uuid,
facility_id uuid,
from_node citext,
to_node citext,
from_to_node citext,
from_node_dts timestamp without time zone,
to_node_dts timestamp without time zone,
seconds integer,
cycle_id uuid
);
The duration is pre-calculated in seconds, and the area of interest for now is only the from_to_node name. So, it's fair to think of the example as
CREATE TABLE IF NOT EXISTS data.edge_event (
from_to_node citext,
seconds integer
);
Raw Data
Within the edge_event table, there are 159 distinct from_to_node values over around 300K event rows. Some are found in only a handful of edge_event records, some are found in thousands, or tens of thousands. That's too much to provide a good sample for. But to make the problem simpler to follow, a from_to_node might be
Boxing_Assembly 1256
Meaning "it took 1256 seconds to move this part from the Boxing phase to the Assembly phase." And here we might have 10,000 other records for "Boxing_Assembly" with different durations.
Goal
We're looking for two things out of each from_to_node. For something like Boxing_Assembly, I'm trying to do this:
Sort the seconds taken into buckets, say 20 buckets. This is for a histogram.
For each bucket get the
count of edge_event rows
avg(seconds) within the bucket
min/first_value(seconds) within the bucket
max/last_value(seconds) within the bucket
So, we're looking to chart durations to look for clusters, and then get the raw seconds out of any common clusters.
What I've tried
I've tried a lot of different code, and I've not succeeded. It seems like a problem for GROUP BY and/or window functions. There's something I'm not getting, as my results are far from the mark.
I know that I haven't provided sample data, which makes it harder to help. But I'm guessing that what I'm missing is one++ concepts. Pretty much, I want to know how to split out the edge_event data by from_to_node and then by seconds. Given the huge ranges across from_to_nodes, I'm trying to bucket each individually based on their own min/max.
Thanks very much for any help.
Draft Attempt
I've developed a query that works a bit, but not entirely. This is an edit from my original post with broken code.
WITH
min_max AS
(
SELECT from_to_node,
min(seconds),
max(seconds)
FROM edge_event
GROUP BY from_to_node
)
SELECT edge_event.from_to_node,
width_bucket (seconds, min_max.min, min_max.max, 99) as bucket, -- Bucket are counted from 0, so 9 gets you 10 buckets, if you have enough data.
count(*) as frequency,
min(seconds) as seconds_min,
max(seconds) as seconds_max,
max(seconds) - min(seconds) as bucket_width,
round(avg(seconds)) as seconds_avg
FROM edge_event
JOIN min_max ON (min_max.from_to_node = edge_event.from_to_node)
WHERE min_max.min <> min_max.max AND -- Can't have a bucket with an upper and lower bound that are the same.
edge_event.from_to_node IN (
'Boxing_Assembly',
'Assembly_Waiting For QA')
GROUP BY edge_event.from_to_node,
bucket
ORDER BY from_to_node,
bucket
What I'm getting back looks pretty good:
from_to_node bucket frequency seconds_min seconds_max bucket_width seconds_avg
Boxing_Assembly 1 912 17 7052 7035 3037
Boxing_Assembly 2 226 7058 13937 6879 9472
Boxing_Assembly 3 41 14151 21058 6907 16994
Boxing_Assembly 4 16 21149 27657 6508 23487
Boxing_Assembly 5 4 28926 33896 4970 30867
Boxing_Assembly 6 1 37094 37094 0 37094
Boxing_Assembly 7 1 43228 43228 0 43228
Boxing_Assembly 10 2 63666 64431 765 64049
Boxing_Assembly 14 1 94881 94881 0 94881
Boxing_Assembly 16 1 108254 108254 0 108254
Boxing_Assembly 37 1 257226 257226 0 257226
Boxing_Assembly 40 1 275140 275140 0 275140
Boxing_Assembly 68 1 471727 471727 0 471727
Boxing_Assembly 100 1 696732 696732 0 696732
Assembly_Waiting For QA 1 41875 1 18971 18970 726
Assembly_Waiting For QA 9 1 207457 207457 0 207457
Assembly_Waiting For QA 15 1 336711 336711 0 336711
Assembly_Waiting For QA 38 1 906519 906519 0 906519
Assembly_Waiting For QA 100 1 2369669 2369669 0 2369669
One problem here is that the buckets aren't evenly sized...they seem kind of weird. I've also tried specifying 10, 20, or 100 buckets, and get similar results. I'm hoping that there is a better way to allocate the data to buckets that I'm missing, and that there's a way to have zero-entry buckets instead of gaps.
I would use the PostgreSQL optimizer for that. It collects exactly the information you want.
Create a temporary table with the values you are interested in and ANALYZE it. Then look into pg_stats for the following:
if there are "most common values", you have them and their frequency right there.
Otherwise, look for adjacent histogram boundaries that are close together. Such a bucket is an interval where values are "lumped".
There are some functions in Q/KDB that let us aggregate on a sliding window (msum, mavg, etc.). But these functions takes the number of previous rows into account.
I'd like a function that would aggregate on a sliding window but with time instead of number of rows. For example on the last 5 minutes.
Do such functions exist? If not, how can I design it? I don't want to use a while loop, as it will slow down my program too much because of the huge amount of data.
Thank you for your help
do you want to aggregate to fixed time buckets by and xbar are your friend: http://code.kx.com/q/ref/arith-integer/#xbar
trade: ([] time:`time$(10:00 10:01 10:03 10:07 10:09); price:`float$(12.1 12.6 12.4 12.4 12.9); size:`int$(5 6 10 34 2))
select last price, sum size by 5 xbar time.minute from trade
minute| price size
------| ----------
10:00 | 12.4 21
10:05 | 12.9 36
if you want to go back 5 minutes in time for every row a window join is what your are looking for: http://code.kx.com/q/ref/joins/#wj-wj1-window-join
w:-300000 0+\:trade.time
wj1[w;`time;trade;(trade;(last;`price);(sum;`size))]
time price size
-----------------------
10:00:00.000 12.1 5
10:01:00.000 12.6 11
10:03:00.000 12.4 21
10:07:00.000 12.4 44
10:09:00.000 12.9 36
I have a list of employees and turn-around times, like so:
order | employee | turn-around
------------------------------
1 | Mark | 1
2 | Mark | 2
3 | Mark | 10
4 | John | 1
5 | John | 5
6 | John | 20
7 | Chad | 15
8 | Chad | 20
9 | Chad | 60
So, as you can see, the data ends to be skewed somewhat, and so I'd like to summarize each employee by their median turn-around:
employee | median turn-around
-----------------------------
Mark | 2
John | 5
Chad | 20
I'd also like to present each employee with a comparison of how they're doing compared to the other employees. For this summary, I'd like to use the difference from the median of the medians:
employee | median turn-around | median absolute difference
----------------------------------------------------------
Mark | 2 | -3
John | 5 | 0
Chad | 20 | +15
I'd like to have this automatically done in Crystal Reports 2013 so each employee gets their own page with a histogram of their turn-around times, their median turn-around time, and how it compares to the median of all the other employees' median turn-around times.
Alas, my crystal-fu is failing me in the last part. I have grouped the records by employee, created a formula field to calculate the turn-around time in the details, and created a formula to retrieve the median turn-around for the employee in the group footer. I've managed to create my histogram. But I cannot for the life of me figure out how to aggregate the group medians and report the median of that median without querying the same data again using a subreport. Is it possible to accomplish this without a subreport?
I have that kind of data in a google spreadsheet:
| Day 1 | Day 2 | Day 3
Marc | 10 | 5 | 8
Amy | - | 15 | 3
What I would like is a chart that shows that marc had a total of 10 on day 1, 15 on day 2 and 23 on day 3 and Amy didn't exist on day 1 then had 15 on day 2 then 18 on day 3.
The ideal would be an automated solution that generates directly the chart but I guess i could extract some data to an other sheet and use for my chart. For instance:
| Day 1 | Day 2 | Day 3
Marc | 10 | 15 | 23
Amy | - | 15 | 18
If that's the only solution, how would I generate such a table automatically based on the input of my first table knowing that new names may be added and each day a column will be added ?
Thanks
Simple way
Just make plot with bars and see cumulative sums in chart. You won't see exact number though:
Hard Way
Or prepare another table with new calculated sums. Suppose, your data is placed on sheet \1/. Add another sheet and paste formulas:
="1!R2C2:"&"R"&COUNTA('1'!A:A)+1&"C"&counta('1'!1:1)+1 in cell A1 to count work range
={'1'!B1:1} in cell B1 to copy 'Days' labels.
={'1'!A2:A} in cell A2 to copy names
And finally paste this hard formula in cell B2:
=mmult(ArrayFormula(MMULT(ArrayFormula(row(INDIRECT(A1,0))^0),SPLIT(ArrayFormula(CONCATENATE("-"&INDIRECT(A1,0))),"-"))*ArrayFormula(--(SPLIT(ArrayFormula(CONCATENATE("-"&if(COLUMN(INDIRECT(A1,0)),row(INDIRECT(A1,0))))),"-")=ArrayFormula(row(OFFSET('1'!A2,,,COUNTA('1'!A:A))))))),ArrayFormula(--(TRANSPOSE(SPLIT(ArrayFormula(CONCATENATE("-"&if(row(INDIRECT(A1,0)),COLUMN(INDIRECT(A1,0))))),"-"))<=ArrayFormula(COLUMN(OFFSET('1'!B1,,,1,COUNTA('1'!1:1)))))))
Then plot your new calculated data to make something like this:
Note that I changed "-" by 0 to make data look like numbers.
Also zero's are listed as empty string ''. This is made by custom number format: 0;0;
Please, look at Working example
I have another challenge that I am trying to resolve but unable to get the solution yet. Here is the scenario. Pardon the formatting if it messes up at the time of posting.
ACCT_NUM CERT_ID Code Date Desired Output
A 1 10 1/1/2007 1/1/2008
A 1 10 1/1/2008 1/1/2008
A 1 20 1/1/2009 1/1/2010
A 1 20 1/1/2010 1/1/2010
A 1 10 1/1/2011 1/1/2012
A 1 10 1/1/2012 1/1/2012
A 2 20 1/1/2007 1/1/2008
A 2 20 1/1/2008 1/1/2008
A 2 10 1/1/2009 1/1/2010
A 2 10 1/1/2010 1/1/2010
A 2 30 1/1/2011 1/1/2011
A 2 10 1/1/2012 1/1/2013
A 2 10 1/1/2013 1/1/2013
As you can see, I need to do a MAX on the date based on each group of code values (apart from ACCT_NUM and CERT_ID) before the value changes. If the same value repeats, I need to a MAX of the data again for that group separately. For example, for CERT_ID of '1', I cannot group all four rows of Code 10 to get a MAX date of 1/1/2012. I need to get the MAX for the first two rows and then another MAX for the next two rows separately since there is another code in between. I am trying to accomplish this in Cognos Framework Manager.
Gurus, please advise.
The syntax for getting the max value for CERT_ID is:
maximum(Date for CERT_ID)
If you want additional level/s for max you can use the following syntax:
maximum(Date for ACCT_NUM,CERT_ID,Code)
In general, it is best practice to group and summarize values in report, not in framework manager.