I am trying to use a expression within an expression in SSRS and it's getting really complicated. Is there a way around this?
For example if I have a number of sales and number of contacts I can create the conversion rate by dividing the sales into the contacts ie
=fields!sales.value/fields!contacts.value
What I want to do next is use this to put the sales people into various bands so that those with a conversion rate in thresholds are displayed in bandings.
=iif(fields!sales.value/fields!contacts.value<0.5,"poor","Ok")
This is fine for 2 bandings (ok and poor), but gets more complicated for the 5 bandings I want.
I must be able to define the first variable and then use that within the iif statement?
How do I do this in SSRS 2008?
Thanks in advance.
Better to use Switch which returns the first true condition
=Switch(
fields!sales.value/fields!contacts.value < value1, "very poor",
fields!sales.value/fields!contacts.value < value2, "poor",
...
fields!sales.value/fields!contacts.value < value(n-2), "good",
fields!sales.value/fields!contacts.value < value(n-1), "very good",
True, "excellent"
)
where value1 < value2 < ... < valuen.
The final True is dummy like the use of default in an SQL Case expression
An alternative is using custom vb code you can create a function
Public Function GetRating( ByVal rating As Decimal ) As String
Select Case rating
Case Is < value1
Return "poor"
...
Case Is < valuen
return "very good"
Case Else
Return "excellent"
End Function
Then in the rows use the expression
= Code.GetRating( fields!sales.value/fields!contacts.value )
Related
I have a report which creates a spreadsheet. one cell could have data from one of three fields depending on a fourth field status or field two being blank..
I was thinking of writing as CASE statement but that does not work in ssrs.
The IIF statement works great for 2 values but how do you write for three values?
In common language it would be "If secondary value ="Yes", use secondary name, If account field value is Null, use Contact field value, otherwise use account field value"
Thanks
You can use nested IIF statements but they quickly get messy. You should use SWITCH which acts a bit like a case statement.
A simple example would be
= SWITCH(
Fields!myFirstField.Value = <10 , "Small",
Fields!myFirstField.Value = <30 , "Medium",
Fields!myFirstField.Value = <80 , "Large",
True , "HUGE",
)
As switch stops at the first true expression there is not need to check ranges of values if you get them in the correct order.
The final "True" expression just acts like an ELSE
If you need to check multiple criteria per condition then you can do that too like this..
= SWITCH(
Fields!myFirstField.Value = <10 AND Fields!mySecondField.Value = 1 , "Small Cat",
Fields!myFirstField.Value = <10 AND Fields!mySecondField.Value = 2 , "Small Dog",
Fields!myFirstField.Value = <30 , "Medium Animal",
Fields!myFirstField.Value = <80 , "Large Animal",
True , "HUGE Animal",
)
There must be a way in SSRS to have multiple conditionals for separate data filters? I have an input report level filter #reportparameter, and data item "Checknum" I need to do something resembling the following:
if #reportparameter = "C" and Left(Fields!Checknum,2) = "NC", filter
otherwise
if #reportparameter = "E" and Left(Fields!Checknum,2) = "VR", then filter
two separate conditionals, both compound statements.
What does the SSRS Dataset look like, as far as syntax?
If you want this as part of the query, you could add it to the WHERE clause:
WHERE (#reportparameter = 'C' and Left(Fields!Checknum,2) = 'NC')
OR (#reportparameter = 'E' and Left(Fields!Checknum,2) = 'VR')
But if you want to do it in the dataset filter, your filter Expression would be like
=IIF((Parameters!reportparameter.Value= "C" AND LEFT(Fields!Checknum.Value, 2) = "NC")
OR (Parameters!reportparameter.Value= "E" AND LEFT(Fields!Checknum.Value, 2) = "VR")
, 1, 0)
The type would be Integer and the Value would be 1.
I am hoping that someone can modify my existing query and provide me the SQL for me to copy and paste based on my 2 conditions listed below. Thank you very much in advance, Nathaniel
condition#1. compare the values of the following 3 fields and output the lowest value of the 3 fields (exlcuding null values):
"lowest list price"
"lowest price sold"
"lining_price_exception"
example: if "lowest list price" = 3 and "lowest price sold" = 7 and "lining_price_exception" =null, then the output should be 3.
conditon#2. if the value in the field "overide_price" is not null, then the field "overide_price" should replace the output from from condition #1. if the value in "overide_price" is null, then output the value from condition#1.
SELECT q.Part_ID, q.[lowest list price], q.[lowest price sold],
q.lining_price_exception, q.overide_price
FROM qry_to_determine_wmx_price_01 AS q;
This should be complicated enough for you. Here is tested SQL no need to define any VBA methods which meets both criteria:
Select q.Part_ID,
q.[lowest list price],
q.[lowest price sold],
q.lining_price_exception,
q.overide_price,
NZ(q.overide_price,
IIf(q.[lowest list price]<q.[lowest price sold] OR ISNULL(q.[lowest price sold]),
IIf(q.[lowest list price]<q.lining_price_exception or ISNULL(q.lining_price_exception),
NZ(q.[lowest list price],"No valid Price listed"),
q.lining_price_exception
),
IIf(q.[lowest price sold]<q.lining_price_exception or ISNULL(q.lining_price_exception),
NZ(q.[lowest price sold],"No valid Price listed"),
q.lining_price_exception
)
)
) as Actual_Low_Price
from qry_to_determine_wmx_price_01 as q;
If you will be running your query from within an Access session, you can use a custom VBA function to make this easier.
Testing the MinValue() function in the Immediate window ...
? MinValue(4, Null, 2)
2
? MinValue(Null, Null, 2)
2
? MinValue(Null, Null, Null)
Null
So you could tackle your condition#1 in a query like this ...
SELECT
MinValue(
q.[lowest list price],
q.[lowest price sold],
q.lining_price_exception
) AS lowest_value
qry_to_determine_wmx_price_01 AS q;
As for your conditon#2, I think the Nz() function would be useful.
Nz(q.overide_price, MinValue(q.[lowest list price], q.[lowest price sold],
q.lining_price_exception))
Basically that Nz() expression says "return overide_price if it's not Null, otherwise return the value from the MinValue() expression".
This is the function I mentioned.
Public Function MinValue(ParamArray pValues() As Variant) As Variant
Dim i As Long
Dim iUbound As Long
Dim varMin As Variant
iUbound = UBound(pValues)
varMin = Null
For i = 0 To iUbound
If Not IsNull(pValues(i)) Then
If Not IsNull(varMin) Then
If pValues(i) < varMin Then
varMin = pValues(i)
End If
Else
varMin = pValues(i)
End If
End If
Next
MinValue = varMin
End Function
Hopefully someone can help me out with this. I have written a query in Access 2003 that combines a linked table "taxon_group_max_per_site" and a cross tab query "Distinct Species by group_Crosstab".
From the table I have the field "Taxonomic Group" and "Max", and from the cross tab the fields "Total_Of_Species_S".
The table and the cross tab are linked and the query works fine until I add in some VBA to give each Taxonomic group a score based on "Max" and "Total_Of_Species_S".
The code below brings up "Error 13: type mismatch"
Public Function Invert_Diversity_Score (Total_Of_Species_S As Integer) As Integer
If Total_Of_Species_S < Round("[Max]*0.5", 0) Then
Invert_Diversity_Score = 0
Else
If Total_Of_Species_S < Round("[Max] * 0.75", 0) Then
Invert_Diversity_Score = 1
Else
If Total_Of_Species_S < Round("[Max] * 0.875", 0) Then
Invert_Diversity_Score = 2
Else
Invert_Diversity_Score = 3
End If
End If
End If
End Function
The debugger shows that "[Max]*0.5" and the other multiplications do not produce a number it says "[Max] * 0.5"= "[Max] * 0.5", which I think is the source of the type mismatch. How do I get the field to multiple properly? It looks exactly like the format shown in the VBA help.
The round function is expecting a number as parameter, not a string! Assuming (max) is a number, you can then calculate:
Round([Max] * 0.75, 0)
But
Round("[Max] * 0.75", 0)
Will definitely not return anything viable
"[Max] * 0.875" is just a string, how is VBA supposed to know that you are referring to the column [Max] from one of your tables?
Shouldn't [Max] be passed into the function as a second integer parameter? Something like this:
Public Function Invert_Diversity_Score (Total_Of_Species_S As Integer,
MaxVal as Integer) As Integer
We need the code that shows how you are calling the function to really sort this out ...
For one, you should use the ElseIf keyword, there is no need to stack the Ifs here.
Second - what is "[Max]*0.5" supposed to mean? To VB, it is a string, which unsurprisingly you can't multiply with an integer.
Assuming Max is some kind of global constant:
Public Function Invert_Diversity_Score(Total_Of_Species_S As Integer) As Integer
If Total_Of_Species_S < Round(Max * 0.5, 0) Then
Invert_Diversity_Score = 0
ElseIf Total_Of_Species_S < Round(Max * 0.75, 0) Then
Invert_Diversity_Score = 1
ElseIf Total_Of_Species_S < Round(Max * 0.875, 0) Then
Invert_Diversity_Score = 2
Else
Invert_Diversity_Score = 3
End If
End Function
If it is not a constant, then you must pass it into the function as well:
Public Function Invert_Diversity_Score( _
Total_Of_Species_S As Integer, _
Max as Integer _
) As Integer
I'm trying to select orders that have either over or under 2000 products ordered in them, depending on other values. I need to select the information from the Orders table, but check this value in the OrdersProducts table, specifically the sum of OrdersProducts.ProductQty. I also need to do this using predicate builder, because of other requirements. So far, I have this, but it isn't returning the results correctly. Its using nested Lambda expressions, which I didn't know I could do but I tried it and it works, but its not returning correct results.
Dim getOrders = From d In db.Orders _
Where d.Status = OrderStatus.Approved _
Select d
' Then a for loop adding parameters via Predicatebuilder...
If over2000 = True Then
' over 2000
predicate1 = predicate1.And(Function(d) (d.OrderProducts.Sum(Function(c) c.ProductQty > 2000)))
Else
' under 2000
predicate1 = predicate1.And(Function(d) (d.OrderProducts.Sum(Function(c) c.ProductQty < 2000)))
End If
basePredicate = basePredicate.Or(predicate1)
' End For loop
getOrders = getOrders.Where(basePredicate)
I removed some code for brevity but I think that gets the point across. How can I do this?? Thanks!
Try changing this:
(d.OrderProducts.Sum(Function(c) c.ProductQty > 2000))
to this:
(d.OrderProducts.Sum(Function(c) c.ProductQty) > 2000)
I haven't built this to test it, but it appears that it was currently trying to sum the results of a boolean comparison instead of summing the quantities and then comparing.