Subreport Table data scope issue SSRS - reporting-services

I'm trying to select data from other datasets to include in my table. This is the expression I have so far:
=iif(ReportItems!ID.Value=1
, (First(Fields!NumbBreaker.Value, "sp_Permit11"))
,iif(ReportItems!ID.Value=3
, (First(Fields!MoldProd.Value, "sp_PermitASMoldProd"))
,iif(ReportItems!ID.Value =4
, (First(Fields!MoldProd.Value, "sp_PermitASMoldProd"))
,iif(ReportItems!ID.Value =5
, (First(Fields!Thermal.Value, "sp_PermitThermalSand"))
,iif(ReportItems!ID.Value=6
, ((First(Fields!Steel20T.Value, "sp_Permit11")) + (First(Fields!Steel9T.Value, "sp_Permit11")) + (First(Fields!Ductile.Value, "sp_Permit11")))
,iif(ReportItems!ID.Value=7
, ((First(Fields!Steel20T.Value, "sp_Permit11")) + (First(Fields!Steel9T.Value, "sp_Permit11")))
,iif(ReportItems!ID.Value=8
, (First(Fields!IMF.Value, "sp_Permit11"))
,iif(ReportItems!ID.Value=9
, (First(Fields!Ductile.Value, "sp_Permit11"))
,iif(ReportItems!ID.Value = 10
, (First(Fields!DM1.Value, "sp_PermitDM1"))
,iif(ReportItems!ID.Value = 12
, (First(Fields!Zircon.Value, "sp_PermitZircon"))
,iif(ReportItems!ID.Value = 14
, (First(Fields!CMN.Value, "sp_PermitCMN"))
,iif(ReportItems!ID.Value = 15
, (First(Fields!A270.Value, "sp_Permit270"))
,iif(ReportItems!ID.Value= 16
, (First(Fields!A290.Value, "sp_Permit290"))
,iif(ReportItems!ID.Value = 17
, (First(Fields!CM8.Value, "sp_PermitCM8"))
,iif(ReportItems!ID.Value = 20
, (First(Fields!NT.Value, "sp_PermitNT")),"")))))))))))))))
How can I do this without using the First? The first is only bringing in the first value but without it I get:
Report item expressions can only refer to fields within the current
dataset scope or, if inside an aggregate, the specified dataset scope

You can't select data from another dataset without specifying which data you want. This is why you need the First function - it is the easiest way to specify what to select from the other dataset.
However, there are other ways to select the data that you want. I'll assume that each dataset has the unique ID field so we can use the Lookup function. Also, let's change from using IIF and use Switch instead as it is a bit more convenient for this sort of statement.
Now your expression will look like this:
=Switch(
ReportItems!ID.Value = 1, Lookup(Fields!ID.Value, Fields!ID.Value, Fields!NumbBreaker.Value, "sp_Permit11"),
ReportItems!ID.Value = 3, Lookup(Fields!ID.Value, Fields!ID.Value, Fields!MoldProd.Value, "sp_PermitASMoldProd"),
ReportItems!ID.Value = 4, Lookup(Fields!ID.Value, Fields!ID.Value, Fields!MoldProd.Value, "sp_PermitASMoldProd"),
ReportItems!ID.Value = 5, Lookup(Fields!ID.Value, Fields!ID.Value, Fields!Thermal.Value, "sp_PermitThermalSand"),
ReportItems!ID.Value = 6, Lookup(Fields!ID.Value, Fields!ID.Value, Fields!Steel20T.Value, "sp_Permit11") + Lookup(Fields!ID.Value, Fields!ID.Value, Fields!Steel9T.Value, "sp_Permit11") + Lookup(Fields!ID.Value, Fields!ID.Value, Fields!Ductile.Value, "sp_Permit11"),
ReportItems!ID.Value = 7, Lookup(Fields!ID.Value, Fields!ID.Value, Fields!Steel20T.Value, "sp_Permit11") + Lookup(Fields!ID.Value, Fields!ID.Value, Fields!Steel9T.Value, "sp_Permit11"),
ReportItems!ID.Value = 8, Lookup(Fields!ID.Value, Fields!ID.Value, Fields!IMF.Value, "sp_Permit11"),
ReportItems!ID.Value = 9, Lookup(Fields!ID.Value, Fields!ID.Value, Fields!Ductile.Value, "sp_Permit11"),
ReportItems!ID.Value = 10, Lookup(Fields!ID.Value, Fields!ID.Value, Fields!DM1.Value, "sp_PermitDM1"),
ReportItems!ID.Value = 12, Lookup(Fields!ID.Value, Fields!ID.Value, Fields!Zircon.Value, "sp_PermitZircon"),
ReportItems!ID.Value = 14, Lookup(Fields!ID.Value, Fields!ID.Value, Fields!CMN.Value, "sp_PermitCMN"),
ReportItems!ID.Value = 15, Lookup(Fields!ID.Value, Fields!ID.Value, Fields!A270.Value, "sp_Permit270"),
ReportItems!ID.Value = 16, Lookup(Fields!ID.Value, Fields!ID.Value, Fields!A290.Value, "sp_Permit290"),
ReportItems!ID.Value = 17, Lookup(Fields!ID.Value, Fields!ID.Value, Fields!CM8.Value, "sp_PermitCM8"),
ReportItems!ID.Value = 20, Lookup(Fields!ID.Value, Fields!ID.Value, Fields!NT.Value, "sp_PermitNT"),
True, "")
So we look up the value we want in the other dataset based on a unique key in the current dataset and return whichever field we want from the other dataset. The True, "" bit at the end is effectively the else condition - it is what is returned if no other condition is met.

Related

AWK: filtering of the lines based on the column similarity

I am dealing with the post-processing of multi-column CSV arranged in fixed format:
ID, POP, dG
1, 12, -5.6500
2, 10, -5.5100
3, 14, -5.3500
4, 17, -5.3400
5, 8, -5.3000
6, 1, -5.1800
7, 12, -5.1700
8, 7, -5.1500
9, 3, -5.1100
10, 6, -5.0200
11, 2, -5.0100
12, 2, -4.9500
13, 1, -4.9000
14, 14, -4.8400
15, 4, -4.8300
16, 2, -4.8300
17, 6, -4.7700
18, 7, -4.7600
19, 3, -4.7200
20, 6, -4.7100
I need to reduce the number of the lines in this data focusing i) on the search of the line with the highest number in the second column, pop(MAX); ii) while keeping in the output the lines with the POP column > or = 0.6*pop(MAX); and iii) keep always the first line (with the ID 1). I've used the following AWK expression for the practical realisation:
awk -F ', ' 'NR == 1 {next} FNR==NR {if (max < $2) max=$2; next} FNR == 2 || $2 > (.6 * max)' input.csv input.csv > output.csv
that gives me the following output.csv
ID, POP, dG
1, 12, -5.6500
3, 14, -5.3500
4, 17, -5.3400
7, 12, -5.1700
14, 14, -4.8400
How could I modify my AWK expression to include additionally the next line after POP MAX if it matches another condition with the lower persentatage similarity to pop max: POP > or = 0.4*pop(MAX),
so the output should consist additional string if its POP column fit the rule (I added # coments to clarify the selection of each line):
ID, POP, dG
1, 12, -5.6500 # the first line is always taken
3, 14, -5.3500 # POP > or = 0.6*pop(MAX)
4, 17, -5.3400 # it is POP MAX
5, 8, -5.3000 # it is the string next to pop max: POP > or = 0.4*pop(MAX)
7, 12, -5.1700 # POP > or = 0.6*pop(MAX)
14, 14, -4.840 # POP > or = 0.6*pop(MAX)
You may use this awk:
awk -F ', ' 'NR == 1 {next} FNR==NR {if (max < $2) {max=$2; n=FNR+1} next} FNR <= 2 || FNR == n || $2 > (.6 * max)' input.csv input.csv
ID, POP, dG
1, 12, -5.6500
3, 14, -5.3500
4, 17, -5.3400
5, 8, -5.3000
7, 12, -5.1700
14, 14, -4.8400
To make it more readable:
awk -F ', ' '
NR == 1 {next}
FNR == NR {
if (max < $2) {
max = $2
n = FNR+1
}
next
}
FNR <= 2 || FNR == n || $2 > (.6 * max)
' input.csv{,}
input.csv{,} is brace expansion in bash that just repeats string twice to make it input.csv input.csv

AWK: filtering of the data based on TWO column information

I am working on post-processing of multi-column CSV arranged in multi-column format:
ID, POP, dG
1, 10, -5.6200
2, 4, -5.4900
3, 1, -5.3000
4, 4, -5.1600
5, 4, -4.8800
6, 3, -4.7600
7, 2, -4.4900
8, 5, -4.4500
9, 2, -4.4400
10, 8, -4.1400
11, 1, -4.1200
12, 2, -4.0900
13, 5, -4.0100
14, 1, -3.9500
15, 3, -3.9200
16, 10, -3.8800
17, 1, -3.8700
18, 3, -3.8300
19, 1, -3.8200
20, 3, -3.8000
Previously I have used the following AWK sollution to process the inout log two times, detect pop(MAX) and save linnes which matched $2 > (.8 * max)':
awk -F ', ' 'NR == 1 {next} FNR==NR {if (max < $2) {max=$2; n=FNR+1} next} FNR <= 2 || (FNR == n && $2 > (.4*max)) || $2 > (.8 * max)' input.csv{,} > output.csv
that could reduce the input log keeping just two linnes with highest POP:
ID, POP, dG
1, 10, -5.6200
16, 10, -3.8800
Now I need to change the search algorithm taking into account the both 2nd (POP) and 3rd(dG) columns: i) always taking the first line as the reference, which always has most negative number in the 3rd column (dG); ii) finding the line which has biggest number in the second column, pop(MAX);
iii) taking all linnes between (i) and (ii) that will match the following rule applied for the BOTH columns:
a) line should have (negative) number in 3rd column, matching following the rule: $1 > (.5 * $1(min))', where $1(min) is the number (dG) of the first line (always most negative)
b) additionally line should match the old rule for the second column with decreased threshold : $2 = or > (.5 * max)', where max is the pop(MAX)
So an expecting output should be
ID, POP, dG
1, 10, -5.6200. # this is the first line with most negative dG
8, 5, -4.4500 # this has POP (5) and dG (-4.4500) matching the both rules
10, 8, -4.1400. # this has POP (8) and dG (-4.1400) matching the both rules
16, 10, -3.8800 # this is pop max, with higher POP
ADDED 8-04:
For the case if the first line has with very low POP (which does not match the rule $2 >= (.5 * maxPop)
ID, POP, dG
1, 5, -5.5600
2, 7, -5.3300
3, 7, -5.1900
4, 1, -4.6800
5, 1, -4.5800
6, 5, -4.5600
7, 3, -4.4700
8, 4, -4.4300
9, 9, -4.4200
10, 4, -4.4200
11, 2, -4.3800
12, 4, -4.3400
13, 25, -4.3000
14, 6, -4.2900
15, 8, -4.2600
16, 3, -4.2300
17, 1, -4.1800
18, 3, -4.1300
19, 1, -4.1300
20, 1, -4.1200
21, 27, -4.0800
22, 2, -4.0300
the output should not contain the first line either while still using its value from dG column as the reference for the second condition ($3 <= (.5 * minD), which should be applied for the selection of other linnes in the output:
13, 25, -4.3000
21, 27, -4.0800
You may use this awk solution:
awk -F ', ' 'NR == 1 {next} FNR==NR {if (maxP < $2) maxP=$2; if (minD=="" || minD > $3) minD=$3; next} FNR <= 2 || ($2 >= (.5 * maxP) && $3 <= (.5 * minD))' file{,}
ID, POP, dG
1, 10, -5.6200
8, 5, -4.4500
10, 8, -4.1400
13, 5, -4.0100
16, 10, -3.8800
To make it more readable:
awk -F ', ' '
NR == 1 {next} # skip 1st record 1st time
FNR == NR {
if (maxP < $2) # compute max(POP)
maxP = $2
if (minD == "" || minD > $3) # compute min(dG)
minD = $3
next
}
# print if 1st 2 lines OR "$2 >= .5 * max(POP) && $3 <= .5 * min(dG)"
FNR <= 2 || ($2 >= (.5 * maxP) && $3 <= (.5 * minD))
' file{,}

error: octave_base_value::save_ascii(): wrong type argument 'object'

How can I fix to save, write command in octave?
Import_Data
error: octave_base_value::save_ascii(): wrong type argument 'object'
DATASET.TSERIES = csvread(’MR_AER_DATASET1.csv’);
DATASET.LABEL = {’DATES’,’T_PI’,’T_CI’,’m_PI’,’m_CI’,’APITR’,’ACITR’,’PITB’,’CITB’,’GOV’};
DATASET.VALUE = [ 1, 2, 3, 4, 5 , 6 , 7 , 8 , 9 , 10 ];
DATASET.UNIT = [ 0, 2, 2, 2, 2 , 2, 2 , 1 , 1 , 1 ];
save (’DATASET’, ’DATASET’);

Boolen check if datetime.now() is between the values of any tuple in a list of tuples

I have a list of tuples looking like this:
import datetime as dt
hours = [(dt.datetime(2019,3,9,23,0), dt.datetime(2019,3,10,22,0)),
(dt.datetime(2019,3,10,23,0), d.datetime(2019,3,11,22,0))]
The list has a variable length and I just need a boolean if datetime.now() is between the first and second element of any tuple in the list.
In NumPy I would do:
((start <= now) & (end >= now)).any()
what is the most efficient way to do this in a pythonic way? Sorry about the beginners question.
this works but I don't like the len():
from itertools import takewhile
len(list(takewhile(lambda x: x[0] <= now and now <= x[1], hours ))) > 0
any better suggestions?
any(map(lambda d: d[0] <= now <= d[1], hours))
any: Logical OR across all elements
map: runs a function on every element of the list
As #steff pointed out map is redundant, because we cause list enumeration directly.
any(d[0] <= now <= d[1] for d in hours)
It would be way better if we can avoid indexing into tuple and use tuple unpacking somehow (this was the reason I started with map)
A more verbose alternative. (But more readable in my eyes)
import datetime as dt
def in_time_ranges(ranges):
now = dt.datetime.now()
return any([r for r in ranges if now <= r[0] and r[1] >= now])
ranges1 = [(dt.datetime(2019, 3, 9, 23, 0), dt.datetime(2019, 3, 10, 22, 0)),
(dt.datetime(2019, 3, 10, 23, 0), dt.datetime(2019, 3, 11, 22, 0)),
(dt.datetime(2019, 4, 10, 23, 0), dt.datetime(2019, 5, 11, 22, 0))]
print(in_time_ranges(ranges1))
ranges2 = [(dt.datetime(2017, 3, 9, 14, 0), dt.datetime(2018, 3, 10, 22, 0)),
(dt.datetime(2018, 3, 10, 23, 0), dt.datetime(2018, 3, 11, 22, 0)),
(dt.datetime(2018, 4, 10, 23, 0), dt.datetime(2018, 5, 11, 22, 0))]
print(in_time_ranges(ranges2))
Output
True
False

Sum of a nested iif statement

I have the following nested iif statement that brings back an error "End of Statement expected."
Can someone please help? I know its probably very straightforward but i have been looking at this for sometime.
Thanks
=SUM(IIF(Fields!Grade.Value = "A*", 6, IIF(Fields!Grade.Value = "A", 5, IIF(Fields!Grade.Value = "B", 4, IIF(Fields!Grade.Value = "C" , 3, IIF(Fields!Grade.Value = "D" , 2 , IIF(Fields!Grade.Value = "E", 1, IIF(Fields!Grade.Value = "E/U", 0))))))) - IIF(Fields!Target_Grade.Value = "A*" , 6, IIF(Fields!Target_Grade.Value = "A", 5, IIF(Fields!Target_Grade.Value = "B", 4 , IIF(Fields!Target_Grade.Value = "C", 3, IIF(Fields!Target_Grade.Value = "D", 2, IIF(Fields!Target_Grade.Value = "E" , 1, IIF(Fields!Target_Grade.Value = "U", 0)))))))))
I needed an else 0 statement, added this to the code to give the below and all is good
=SUM(IIF(Fields!Grade.Value = "A*", 6, IIF(Fields!Grade.Value = "A", 5, IIF(Fields!Grade.Value = "B", 4, IIF(Fields!Grade.Value = "C" , 3, IIF(Fields!Grade.Value = "D" , 2 , IIF(Fields!Grade.Value = "E", 1, IIF(Fields!Grade.Value = "E/U", 0, 0))))))) - IIF(Fields!Target_Grade.Value = "A*" , 6, IIF(Fields!Target_Grade.Value = "A", 5, IIF(Fields!Target_Grade.Value = "B", 4 , IIF(Fields!Target_Grade.Value = "C", 3, IIF(Fields!Target_Grade.Value = "D", 2, IIF(Fields!Target_Grade.Value = "E" , 1, IIF(Fields!Target_Grade.Value = "U", 0, 0))))))))
I think you have one too many closing brackets- you could try removing the last bracket.
(I pasted your code into Notepad++ and put in a carriage return for each opening bracket and closing bracket. Notepad++ highlights the matching opening and closing brackets, and there was one left over))