cognos report studio multiple columns average - business-intelligence

Im relatively new to cognos so please bear this in mind.
I wanted to create a report in report studio where i have 3 measures ( A ,B , C ) as columns and a 3rd calculated column as the average of these columns.
However , when using the average function , i cannot add multiple inputs .
i tried the arithmetic alternative ( a+b+c)/3 because this will not handle cases when values are null
Thank you in advance

If nulls are not zero for average
case when
not (a is null and b is null and c is null)
then
(coalesce(a,0) + coalesce(b,0) + coalesce(c,0)) /
(case when a is not null then 1 else 0 end +
case when b is not null then 1 else 0 end +
case when c is not null then 1 else 0 end)
end

I would create a value count expression to count the non-null columns:
Value Count
CASE WHEN [A] is not null THEN 1 ELSE 0
+
CASE WHEN [B] is not null THEN 1 ELSE 0
+
CASE WHEN [C] is not null THEN 1 ELSE 0
Then you can use this new data item as the dividend for your average calculation:
Average
(coalesce([A],0) + coalesce([B],0) + coalesce([C],0))/[Value Count]
If division by 0 is a problem, you can wrap the average expression in another CASE to return null when [Value Count] is 0:
CASE
WHEN [Value Count] > 0 THEN (coalesce([A],0) + coalesce([B],0) + coalesce([C],0))/[Value Count]
ELSE null
END

Related

Power Query How to Assign Values to range of Numbers

I have a range of numbers that I need to assign scores to and would like to see if there's an easy way to do it through Power Query:
>150 = 0,
101-150 = 1,
51-100 = 2,
21-50 = 3,
<=20 = 4
Thanks in advance
The most obvious way is just an if .. then .. else if .. construction as a new custom column similar to this:
Score =
if [value] > 150 then 0
else if [value] >= 101 and [value] <= 150 then 1
else if ...
else if [value] <= 20 then 4
else null

Exclude data with null values in crystal report

I have this formula in crystal reports
Global NumberVar Array Z := [
IF isnull({MIPIRReport;1.1}) then 0 else tonumber({MIPIRReport;1.1}) ,
IF isnull({MIPIRReport;1.2}) then 0 else tonumber({MIPIRReport;1.2}) ,
IF isnull({MIPIRReport;1.3}) then 0 else tonumber({MIPIRReport;1.3}) ,
IF isnull({MIPIRReport;1.4}) then 0 else tonumber({MIPIRReport;1.4}) ,
IF isnull({MIPIRReport;1.5}) then 0 else tonumber({MIPIRReport;1.5}) ,
IF isnull({MIPIRReport;1.6}) then 0 else tonumber({MIPIRReport;1.6}) ,
IF isnull({MIPIRReport;1.7}) then 0 else tonumber({MIPIRReport;1.7}) ,
IF isnull({MIPIRReport;1.8}) then 0 else tonumber({MIPIRReport;1.8}) ,
IF isnull({MIPIRReport;1.9}) then 0 else tonumber({MIPIRReport;1.9}) ,
IF isnull({MIPIRReport;1.10}) then 0 else tonumber({MIPIRReport;1.10}) ];
Minimum (Z)
What I would want is when the data is null, It should be excluded in my report
For graphical example, The values would be like this:
1.1,1.2,1.9,1.5,1.88,0,0,0,0,0
where the 0 represents the null and the 1 represents the values.
I would like to get the minimum value, which would be 1.1 and not 0. How should I do it?
Do take note that each number in the example is a different field in my crystal report which is so named as:
1,2,3,4,5,6,7,8,9,10
You can try 2 ways.
If you want to store null values then you can take 2 arrays one for storing only 0 that is null and another array to store other values.
If you don't need 0 to be stored then change formula this way:
Global NumberVar Array Z;
IF isnull({MIPIRReport;1.1}) then 0 else Z:= tonumber({MIPIRReport;1.1}) ,
IF isnull({MIPIRReport;1.2}) then 0 else Z:= tonumber({MIPIRReport;1.2}) ,
IF isnull({MIPIRReport;1.3}) then 0 else Z:= tonumber({MIPIRReport;1.3}) ,
IF isnull({MIPIRReport;1.4}) then 0 else Z:= tonumber({MIPIRReport;1.4}) ,
IF isnull({MIPIRReport;1.5}) then 0 else Z:= tonumber({MIPIRReport;1.5}) ,
IF isnull({MIPIRReport;1.6}) then 0 else Z:= tonumber({MIPIRReport;1.6}) ,
IF isnull({MIPIRReport;1.7}) then 0 else Z:= tonumber({MIPIRReport;1.7}) ,
IF isnull({MIPIRReport;1.8}) then 0 else Z:= tonumber({MIPIRReport;1.8}) ,
IF isnull({MIPIRReport;1.9}) then 0 else Z:= tonumber({MIPIRReport;1.9}) ,
IF isnull({MIPIRReport;1.10}) then 0 else Z:= tonumber({MIPIRReport;1.10}) ;
Minimum (Z)
Let me know how it goes

How to count how many times delete_if has acted?

I have a code block like this:
hash["value"].delete_if{|cell| cell["id"]["name"] == ('foo')}
There is a simple way to count how many times the delete_if has actually acted ?
counter
Since every integer is truthy, you could write :
count = 0
hash["value"].delete_if{|cell| cell["id"]["name"] == ('foo') && count += 1}
cell will be deleted every time count is incremented, and count is incremented every time cell["id"]["name"] == ('foo').
As an example :
count = 0
true && count += 1
false && count += 1
true && count += 1
false && count += 1
true && count += 1
count
# 3
difference
Since delete_if is destructive, you can simply compare the size difference before and after the method call.
original_size = hash["value"].size
hash["value"].delete_if{|cell| cell["id"]["name"] == ('foo') && count += 1}
original_size - hash["value"].size
partition
If you need not only the number of times delete_if has acted, but for which elements, you could use partition :
deleted, hash["value"] = hash["value"].partition{|cell| cell["id"]["name"] == ('foo')}
deleted.size
# deleted contains the deleted cells from `hash['value']`

label timestamps by intervals in bash

I am using awk to split a file where I have three splits separated by spaces: 1. starting point; 2. ending point; 3. label
I want to create new labels within defined frames which requires an if which is where I am a little stuck.
I am looking for something like this:
num_intervals == (tail -1 | ending point)/250000
count == 1
interval == 2500000
current_interval_start == 0
current_interval_end == current_interval_start + interval
for interval in num_intervals
if starting_point >= current_interval_start and if ending_point <= current_interval_end then
print count + label
count == count + 1
current_interval_start == current_interval_end
current_interval_end == current_interval_start + interval
*observation if two labels are in the same interval range, take the first one, but I could post process this.
My data looks like this:
0 2300000 null
2300000 4300000 h
4300000 8000000 aa
8000000 11500000 t
11500000 28400001 null
What I would like as output would be this:
0 2500000 null
2500000 5000000 h
5000000 7500000 aa
7500000 1000000 aa
1000000 1250000 t
1250000 1500000 null
1500000 1750000 null
1750000 2000000 null
2000000 2250000 null
2500000 2750000 null
2750000 3000000 null
You can do with only awk:
awk -v s=2500000 '{
f=int($1/s);
l=int($2/s);
if((l-f) > 0){
for(i=f+1;i<=l;i++){
a[i]=$3
}
}
}
END {
e=int($2/s);
for (i=0;i<=e;i++){
if (i in a ){
print i*s,(i+1)*s,a[i]
}
else{
print i*s,(i+1)*s,"null"
}
}
}'

How to work with Null in summation

I am doing tot := tot + v_row.SAVINGS; where tot is initialized to 0 and v_row.SAVINGS is initialized to null.
Now I using nvl function to get value 0 instead of null for v_row.Savings as I need 0 in summation if there is Null but when I return v_row, if summation value shows as 0 then I need to have null or blank space value in return, how can I do it.
Note: I am using this for reporting purpose and so if value of summation is zero then I should show null or blank space in report.
NULLIF(expr1, expr2) is logically equivalent to
CASE WHEN expr1 = expr 2 THEN NULL ELSE expr1 END
NVL(expr1, expr2)
tot may be NULL and v_row.SAVINGS may be NULL.
Use NVL to ensure a number is returned for the addition
Use NULLIF to return NULL if the sum is NULL
It may be more appropriate to coerce the tot to NULL just before you return.
Example:
tot := NULLIF(NVL(tot, 0) + NVL(v_row.SAVINGS, 0), 0)
This should work:
tot := case when tot + v_row.SAVINGS = 0 then null else tot + v_row.SAVINGS end;

Resources