Tableau: last value calculation in calculated field - tableau-api

my dataset is like this
KPI VALUE TYPE DATE
coffee break duration 11 0 30/06/2015
coffee break duration 12 0 31/07/2015
coffee break duration 10 0 30/11/2014
coffee break duration 10 0 31/12/2014
coffee expense 20 1 31/07/2015
coffee expense 20 1 31/12/2014
coffee consumers 15 -1 31/07/2015
coffee consumers 17 -1 31/12/2014
for Type, 0 means minutes, 1 means dollars and -1 means people
I want to get a table like this
KPI Year(date) YTD
coffee break duration 2015 11,5
coffee break duration 2014 10
....
YTD calculation is:
if sum([TYPE]) = 0 then avg([VALUE])
elseif sum([TYPE]) > 0 then sum([VALUE])
elseif sum([TYPE]) < 0 then [last value for the considered year]
end
By [Last value for the considered year] I mean the last entry available, in a year if my table is set to Year, otherwise it has to change dynamically based on what Timespan I want to show.
What can I do to have [last value for the considered year] as a calc field ready to use in my YTD calc?
Many thanks,
Stefania

If I understand your question, than you can use LOD in the IF statement
if sum(type) = 0 then avg([value])
elseif sum([type]) > 0 then sum(value)
elseif sum([type]) < 0 then max(if [date] = { INCLUDE kpi: max(date)} then [value] end)
end
If there are several values on the last day of the considered year, it would take the biggest value
I slightly modified your data to show that results are working correctly

Related

How to filter data with starting and ending conditions?

I'm trying to filter my data based on two conditions dependent on sequential dates.
I am looking for values below 2 for 5+ sequential dates,
with a "cushion period" of values 2 to 5 for up to 3 sequential days.
It would look something like this (sorry for the terrible excel attempt here):
Day 1 to Day 10 would be included and day 11 would not be. Days 6 to 8 would be considered the "cushion period." I hope this makes sense!!
Right now, I am able to get the cushion period (in the reprex) only but I cant figure out how to add the start and ending condition for values under 2 for 5 sequential dates to be included (the 5 days could be broken up with the cushion period inbetween but I feel like this might complicate things).
Any help would be GREATLY appreciated!
For my reprex (below), the dates that would be included in the final df are in blue (dates from 1/1/2000 to 1/9/2000, and 1/22/2000 to 1/30/2000) and the dates in grey would not be.
Reprex:
library("dplyr")
#Goal: include all values with values of 2 or less for 5 consecutive days and allow for a "cushion" period of values of 2 to 5 for up to 3 days
data <- data.frame(Date = c("2000-01-01", "2000-01-02", "2000-01-03", "2000-01-04", "2000-01-05", "2000-01-06", "2000-01-07", "2000-01-08", "2000-01-09", "2000-01-10", "2000-01-11", "2000-01-12", "2000-01-13", "2000-01-14", "2000-01-15", "2000-01-16", "2000-01-17", "2000-01-18", "2000-01-19", "2000-01-20", "2000-01-21", "2000-01-22", "2000-01-23", "2000-01-24", "2000-01-25", "2000-01-26", "2000-01-27", "2000-01-28", "2000-01-29", "2000-01-30"),
Value = c(2,3,4,5,2,2,1,0,1,8,7,9,4,5,2,3,4,5,7,2,6,0,2,1,2,0,3,4,0,1))
head(data)
#Goal: values should include dates from 1/1/2000 to 1/9/2000, and 1/22/2000 to 1/30/2000
#I am able to subset the "cushion period" but I'm not sure how to add the starting and ending conditions for it
attempt1 <- data %>%
group_by(group_id = as.integer(gl(n(),3,n()))) %>%
filter(Value <= 5 & Value >=3) %>%
ungroup() %>%
select(-group_id)
head(attempt1)
If I get it correctly, you need to keep groups of consecutive values that are below or equal to 5 with at least 5 consecutive values below or equal to 2 within it. Here's a way to do that, with some explanation:
library(dplyr)
data %>%
mutate(under_three = Value <= 2) %>%
# under_three = TRUE if Value is below or equal to 2
group_by(rl_two = data.table::rleid(Value <= 2)) %>%
# Group by sequence of values that are under_three
mutate(big = n() >= 5 & all(under_three)) %>%
# big = T if there are more 5 or more consecutive values that are below or equal to 2
group_by(rl_five = data.table::rleid(Value <= 5)) %>%
# ungroup by rl_two, and group by rl_five, i.e. consecutive values that are below or equal to 5
filter(any(big))
# keep from the data frame groups of rl_five if they have at least one big = T; remove other groups.
Output:
data %>%
ungroup() %>%
select(Date, Value)
Date Value
1 2000-01-01 2
2 2000-01-02 3
3 2000-01-03 4
4 2000-01-04 5
5 2000-01-05 2
6 2000-01-06 2
7 2000-01-07 1
8 2000-01-08 0
9 2000-01-09 1
10 2000-01-22 0
11 2000-01-23 2
12 2000-01-24 1
13 2000-01-25 2
14 2000-01-26 0
15 2000-01-27 3
16 2000-01-28 4
17 2000-01-29 0
18 2000-01-30 1

Can't figure out date time conversion from int to datetime

I have an application that stores date+time as int in a database.
I would like to get back from the int to the real date&time!
I have these 2 examples:
919326588 ---> 25.03.2022 09:46
919322562 ---> 23.03.2022 14:43
I don't get it, even though I tried with julian days, unix-epoch, seconds from 1.1.1970, ....
Is there anybody out there who can help?
What I got so far is that the beginning is something like:
( 919362588 / 2000 ) + 2000000 --> 2459663.2939999998
The int part is the julian day 2022-03-24. The fraction part should be the fraction of a day in hours, minutes, ...
But it must be more than 0.5 to get over the 00:00 to 2022-03-25, but is only .2939999998 which is less than 0.5 .
assuming that the people dealing with these dates do not count from 12 - 12 but instead from 0 - 0 we have to add 0.5 to get from 12 - 0 midnight.
So this would mean:
0.2939999998 + 0+5 = 0.7939999998
But is 2022-03-25 07:03:21 not 09:46 :-(

Why am I getting an additional riser/bar in my chart in crystal reports

So I have a chart that looks like this:
Here is what I have in the chart expert:
And here is the code for #ZZ_TAT_Name - A:
if {IB_MESSAGES.MSG_ID} = next({IB_MESSAGES.MSG_ID}) and {IB_MESSAGES.MSG_ID} = previous({IB_MESSAGES.MSG_ID}) then "na" else
IF {#Final Turnaround Minutes} > 0 and {#Final Turnaround Minutes} < 15 THEN "UNDER 15"
ELSE IF {#Final Turnaround Minutes} >= 15 and {#Final Turnaround Minutes} < 30 THEN "BETWEEN 15 & 30"
ELSE IF {#Final Turnaround Minutes} >= 30 and {#Final Turnaround Minutes} < 60 THEN "BETWEEN 30 & 60"
ELSE if {#Final Turnaround Minutes} > 60 then "OVER 60"
//else "*Total Messages"
I am wanting to get rid of the riser that shows 11. That riser is the total DistinctCount of IB_MESSAGES.MSG_ID. How would I be able to remove this? Why is this even showing up?
From what you've mentioned below, it seems 11 out of 22 records appear to fall into none of the if-else categories, leading to the unlabeled blue column. The easiest way to proceed is to intervene before the chart is rendered and reduce the incoming data to only values that belong in the other columns:
There's a few ways to handle this, but I would recommend adding an intermediary Formula that returns the exact same records, except any record that doesn't meet the if/else standards will be replaced with null. Something like:
IF (
{IB_MESSAGES.MSG_ID} = next({IB_MESSAGES.MSG_ID})
AND
{IB_MESSAGES.MSG_ID} = previous({IB_MESSAGES.MSG_ID})
)
OR (
{#Final Turnaround Minutes} > 0
AND
{#Final Turnaround Minutes} > 60
)
THEN
//repeat the original value here
ELSE
null
Done correctly, the intermediary formula will return 11 records and 11 nulls when evaluated in the Details section of the report. From here, you can change your chart to read the formula and it should evaluate only 11 non-null values.

Use Lag function in SAS find difference and delete if the value is less than 30

Eg.
Subject Date
1 2/10/13
1 2/15/13
1 2/27/13
1 3/15/13
1 3/29/13
2 1/11/13
2 1/31/13
2 2/15/13
I would need only the subjects with the dates between them more than 30.
required output:
Subject Date
1 2/10/13
1 3/15/13
2 1/11/13
2 2/15/13
This is a very interesting problem. I'll use the retain statement in the DATA step.
Since we are trying to compare dates between different observations, it's a bit more difficult. We can take advantage of the fact that SAS can convert dates to SAS date values (i.e. number of days after Jan 1 1960). Then we can compare these numeric values using conditional statements.
data work.test;
input Subject Date anydtdte15.;
sasdate = Date;
retain x;
if -30 <= sasdate - x <= 30 then delete;
else x = sasdate;
datalines;
1 2/10/13
1 2/15/13
1 2/27/13
1 3/15/13
1 3/29/13
2 1/11/13
2 1/31/13
2 2/15/13
;
run;
proc print data=test;
format Date mmddyy8.;
var Subject Date;
run;
OUTPUT as required:
Obs Subject Date
1 1 02/10/13
2 1 03/15/13
3 2 01/11/13
4 2 02/15/13

crystal reports conditional formatting for summary fields

I'm trying to create a decimal formatting formula on my summary fields. The values in the database could have 0, 1, or 2 decimal places. I've started with this:
If (CurrentFieldValue mod 1 = 0) Then
0
Else If (CurrentFieldValue mod .1 = 0) Then
1
Else
2
On a simple single data field, this works and displays the value with 0, 1, or 2 decimal places based on the data coming from my database. The same formula doesn't work for a summary field on my reports with group data. Any ideas?
Edit: Since I don't know how to format code in a comment, I'll address the suggestion of using a formula here:
Didn't work. Formula:
Sum ({myTable.dataValue}, {myTable.groupField})
then I used:
If ({#formula} mod 1 = 0) Then
0
Else If ({#formula} mod .1 = 0) Then
1
Else
2
And I still got whole numbers for everything. My rounding is set to .01 with no formula. Do I need a formula for rounding too? I still don't understand why this works on individual values but not for group summaries.
OK- it turns out this is due to our lack of understanding of the mod function :)
Everything mod 1 actually returns 0. This is the formula you need to use:
if {ER100_ACCT_ORDER.ER100_ORD_TOT} * 100 mod 100 = 0 then
0
else if {ER100_ACCT_ORDER.ER100_ORD_TOT} * 100 mod 10 = 0 then
1
else
2
:)
How about just creating a formula field instead of using the built-in summary field:
sum({mytable.myfield})
Then you can use your conditional formatting:
If ({#formula} mod 1 = 0) Then
0
Else If ({#formula} mod .1 = 0) Then
1
Else
2