SSRS Data from one dataset not in another - reporting-services

I've been searching for a possible answer to my problem but was unable to find one. Lets assume that I have 2 datasets. dsMediaServerData has two columns: id and channel. I have other dataset (dsCatalogData) with a lot of columns including id and channel. I want to filter dsCatalogData to show only those records that are not in dsMediaServerData.

My recommendation would be to update the SQL queries used to populate the datasets so that duplicate id/channels are excluded.
If you can't do this directly through SQL because the data sets are coming from different DB's, you can accomplish this with the use of a parameter.
1) Let's start with the first dataset (dsMediaServerData in your example). Since your example shows filtering by 2 columns, but the data will be travelling through a single parameter, you will need to create a new column that combines both pieces of data.
SELECT Convert(VARCHAR(255), id) + '_' + Convert(VARCHAR(255), channel) as 'combined_columns_to_filter'
2) Now create a new parameter (let's call it #filter).
Set the data type to text
Check "Allow multiple values".
Open up "Default Values" and choose "Get values from query". Choose the dsMediaServerData data set and select the new column 'combined_columns_to_filter' as the value field.
Set the visibility to "Hidden" so that users don't try to interact with this parameter.
3) Now update the second dataset. Add the #filter parameter to the WHERE clause.
WHERE Convert(VARCHAR(255), id) + '_' + Convert(VARCHAR(255), channel) NOT IN (#filter)
This should effectively filter the second dataset by removing all records found in the first data set even though the data sets are in separate databases.

Related

Comparing multiple fields in two datasets to return a 3rd value

I am in report builder and I have my primary dataset that is from a SQL database, I also then created a second dataset (enter data). I need to compare 2 fields from each dataset to retrieve the correct value from the 2nd dataset and populate a column on my report. I have tried the IIF statements and Lookup statements but I keep getting the error "report item expressions can only refer to fields within the current dataset".
I have a attached a screenshot of what I am trying to do....
The IIF statement I tried to use.. If Acctnum and prodid = each other return IncodeNumber
=IIF((Fields!AcctNum.Value=Fields!AcctNum.Value, "IncodeAccount") AND
(Fields!ProdId.Value =Fields!ProdId.Value, "IncodeAccount")),(Fields!IncodeNumber.Value, "IncodeAccount"),"True")
See code in my problem.
You need to use LOOKUP(). The problem with LOOKUP() is that is can only compare a single value from each dataset. However, we can easily get around this issue by concatenating the two values you need to compare.
Note: This assumes the expression will be in a tablix that is bound to your first dataset and that IncodeAccount is your second dataset - the values you want to lookup. If this is not the case just adjust the expression accordingly
So for you, you probably need to do something like this..
=LOOKUP(
Fields!AcctNum.Value & "||" & Fields!ProdId.Value,
Fields!AcctNum.Value & "||" & Fields!ProdId.Value,
Fields!IncodeNumber.Value,
"IncodeAccount"
)
I've used two pipe symbols to join the values to avoid incorrect matches being found. e.g. Account 123 and product ID 4567 would incorrectly match to Account 1234 and product ID 567 as they would both be 1234567 when joined. By using the || the match would be 123||4567 and 1234||567 respectively.
You may need to convert the values to string using CStr()
Alternative approach
If you are going to do this 'join' multiple times in the same dataset then you could add a calculated column to the dataset that concatenates the two columns. Then you can use this single field in the lookup which will make things a little simpler.
Or, you could do this concatenation in a database view which would make things even easier.

SSRS dropdown with progressive search

Is there a way to make a dropdown in SSRS limit what is shown as a value is typed. As it currently is it just goes to the first item starting with the letter, but in a big list, this still means a lot of scrolling to get to the desired value. This specific report is on SQL Server 2019, but if there is a way to do it for 2016 as well that would be nice to update some of the reports on older servers
Thanks
As far as I know there is no way to do this directly. However, you can do this with some compromise.
Let's say I have a long list of customers that I want to filter.
I create a dataset (dsCustomers) with a dataset query something like
SELECT * FROM customers
I have a parameter which uses this dataset as it's list of available values called pCustomer
If I want to be able to filter this list I would add a new parameter called, say, pCustSearch. This will be a simple parameter with no associated dataset. You can optionally allow NULL values.
Now I can change the dataset query for dsCustomers to be
SELECT *
FROM customers
WHERE (Customername like '%' + #pCustSearch + '%'
OR
#pCustSearch ISNULL)
NOTE: The pCustSearch parameter must be the first parameter (or at least before the pCustomer parameter)
Once you have filled in the search parameter and tab to the main customer drop down, it should filter the values that match what you have typed.

Dynamically change column names as week number on every weekly run

I want to build a SSRS report that has column as week numbers - 8 weeks for 8 columns starting with current. This report is run every week and current week number is set then. So both column names and their values should change .Is it possible to build something like this in SSRS?
I tried doing this with a dynamic SQL based stored proc in dataset. However for every run I don't even see the columns values updating dynamically
Here's an example :
Also I am trying to avoid these week numbers as row values and then using matrices
My stored proc looks something like this
declare #n tinyint = datepart(wk, getdate())
declare #n1 tinyint = (#n+1), #n2 tinyint =(#n+2), #n3 tinyint =(#n+3), #n4 tinyint =(#n+4), #n5 tinyint =(#n+5), #n6 tinyint =(#n+6)
exec ('Select b.sku, b.['+#n+'], b.['+#n1+'], b.['+#n2+'], b.['+#n3+'], b.['+#n4+'], b.['+#n5+']...
Will appreciate any help in this direction.. many thanks!
When working with SSRS it's generally best to avoid dynamic SQL and pivoting the data in the SQL. Use the SQL to get the raw data you need and then let SSRS do the pivoting and aggregation. This way you take advantage of what they each do best. I know you said you want to avoid matrices, but it is the best way to make the report dynamic.
So you should either return all the data in one dataset and use filters on your matrices OR write two queries and have each one populate a matrix. BTW a matrix is just a table with a column group added, so don't be intimidated by them.
There are 2 ways to do this with a standard tablix.
Calculate the column headers as expressions using concatenation of Wk and some date math to find the correct week number and return the same sort of thing from your query (e.g. columns are current_week, week_minus_1, week_minus_2...)
Return the column headers as additional columns in your query that are the same value for every row (e.g. ColHeader0, ColHeader1...). Your data columns would still be relative weeks (e.g. ValueWeek0, ValueWeek1...). In your report the column header would have an expression like =First(Fields!ColHeader0.Value). This is a more flexible approach since it lets you pick 8 historical weeks instead of only the last 8 weeks if you add a parameter.
EDIT - Clarifications
The reason that you get the blank column Wk48 is approximately that you have created your report looking for that column that won't be there the next time. SSRS looks for exact columns. You should you use relative column names for either of the options I have specified:
exec ('Select b.sku, b.['+#n+'] as Wk0, b.['+#n1+'] as Wk1, b.['+#n2+'] as Wk2, b.['+#n3+'] as Wk3, b.['+#n4+'] as Wk4, b.['+#n5+'] as Wk5...
This will allow you to populate the aliased Wk0 column with the appropriate current week data and still make sure that it can be consistently referenced as the base week by SSRS.
To change the column headers you can:
Independently calculate the week numbers in SSRS in the column header expressions: ="Wk" + CStr(<correct week calculation>).
Return the column headers in the result set and access them in the column header expression:
exec ('Select b.sku, b.['+#n+'] as Wk0, b.['+#n1+'] as Wk1, b.['+#n2+'] as Wk2, b.['+#n3+'] as Wk3, b.['+#n4+'] as Wk4, b.['+#n5+'] as Wk5..., ''Wk'''+#n+' as ColHeader0, ''Wk'''+#n1+' as ColHeader1...
and reference the returned column headers from the SSRS column header expression as =First(Fields!ColHeader0.Value).
Here's a solution that worked for me:
Create parameters (say CurrWk, CurrWk1) ,set as hidden and store 'Default value' and 'Available value' equals to current week number (datepart(wk, now()) and any subsequent week by doing a +1, +2, +3.. etc.
Write a query expression . Click onto fx beside dataset query space and write the select query for your program embedding parameter values in the expression window. For eg ="Select SKU, [" & Parameter!CurrWk.Value & "] as Wk1,
[" & Parameter!CurrWk.Value & "] as Wk1 from Sales_Table"
Before passing this query as a 'command text expression' please ensure this query is working in sql ssms.
Save the expression. Now find 'Fields' tab on the left hand side panel.You need to map the fields manually from the query here. If this is not done, there is a very high chance you seean empty field list and wont be able to access them at all. This may be because ssrs do not store query metadata directly from expressions.
You can avoid part of the issue by having atleast the static fields , for example here SKU listed in the 'Fields' list by first running a sql query with static field(select SKU from Sales_Table ). You can then go back to update dataset- change query to expression and embed the parameterized field names.
Map field names. In this example I chose 'Query Type' fields and set Field names as SKU, CurrentWeek, NextWeek and mapped to source SKU, Wk and Wk1 respectively.
Click on 'Refresh Fields' at the bottom. Now you have a dataset with the complete field list. Use these in charts, tables . Run it every week and note the numbers changing as expected.
In case you are using this dataset in a table, make sure you set headers with Labels of Parameters (for eg here I did =Parameters!CurrWk.Label for col with current week data)
That's it!

Report Builder 3.0 Forward Dependency Report Parameter

I have a report that I am working on that will do the following:
Return results based first on the community selected by the user.
Filter to find alike addresses within the community, based on the number of square feet at each address.
Set the end date (a column within the data table) to a user defined parameter for use in a WHERE at the end of the query.
The relevant information is stored in the following places:
Community: ub_subdivision.descr
Address: ub_serv_loc_addr.location_addr
SqFt: arp_ops.dbo.vw_ub_serv_loc_classifications.SqFt
I have setup the query with 3 parameters:
#Community
#Months
#Address
When the user is running the report, the following should happen (in this order):
The community parameter should populate the values stored in ub_subdivision.descr and allow the user to select the community they want from that list.
The address parameter should populate the values within the selected community from step 1, and allow the user to select the address they want from that list.
Based on the selected address, the query should store the value of the SqFt related to this address and use that in the WHERE statement as follows: WHERE (arp_ops.dbo.vw_ub_serv_loc_classifications.SqFt = #Address)
The months parameter should allow for user input to define how many months of data they want. This parameter is called in the query in the WHERE statement: WHERE (ub_bill_run.def_end_dt > DATEADD(m, -#Months, GETDATE())).
If I save the dataset and create a "table report" in Report Builder 3.0 it does the job of recognizing the various parameters and loading them into the Parameters folder and into the Datasets' parameters.
The problem I have is that I am not able to change the parameter properties to display Available Values and select "get from a query". If I go this route, and try to run the query I get an error that I am using "forward dependencies".
I need the #Address parameter to display the address field as the label, but store the sqft field as the value. This is the way I know how to do this and, unfortunately, it doesn't seem to work.
I would appreciate any insight anyone may have.
Thanks!
John
There is one way to solve this make sure the order should be in the order of
#Community
#Months
#Address
change order to:
#Community
#Address
#Months
just delete existing #month and again add it manually and save it.
i hope it will work for you.
You cannot have parameters based on your main data set.
The forward dependency error is caused because your data set is to be filtered by your parameter, yet it is depending on the same data set to find its' set of values. This is a sort of paradox.
When using queries to define the set of values for your parameters, make sure you create a new data set for each parameter.
Next, make sure the parameters are listed in the order you want them to run. Within the data sets for your parameters, you may use where clauses to make them dependent on one another in the order that they run.
In this example:
Parameter data set for Community:
SELECT DISTINCT ub_subdivision.descr
FROM [YOUR JOINED TABLES]
Parameter data set for addresses:
SELECT DISTINCT ub_serv_loc_addr.location_addr
FROM [YOUR JOINED TABLES]
WHERE ub_subdivision.descr IN (#Community)
Parameter data set for SqFt:
SELECT DISTINCT SqFt
FROM [YOUR JOINED TABLES]
WHERE ub_subdivision.descr IN (#Community)
AND ub_serv_loc_addr.location_addr IN (#Address)
You should also make a month data set for your #month parameter, however it is not dependent on the other parameters so I will leave that to you.
Hope this helps!

How do I pass a value returned from one dataset as parameters to a second dataset to return a value from the second dataset in a cell expression?

How do I pass two dynamic values returned from one dataset as parameters to another dataset to return one row of a second dataset in a cell?
For each cell in a header row I need to determine A) Which column to get based off the meal period, and then B) take that value and pass it and another parameter to a query to get one of the columns (I'll take first) from the query.
I am already using cascading parameters, but I'm not sure if or how to use them in this scenario.
Example:
#SalesReceipt
#MealPeriod (A cascaded parameter. There should be one meal period per receipt)
Expression in an example cell:
=IIF(Parameters!#MealPeriod.value = "Lunch", Fields!Burger_Lunch_Type.value, Fields!Burger_Dinner_Type.value)
That returns either the lunch or dinner Type from a fact table, depending on meal period.
Given the Type and Item ID I need to get a value from another query or dataset and add that text to the cell expression. So the expression would look something like:
=IIF(Parameters!#MealPeriod.value = "Lunch", Fields!Burger_Lunch_Type.value, Fields!Burger_Dinner_Type.value) & " and " & (select top row from dataset given the correct type field and Item ID)
The cell should look like: Table1.Type and Table2.Breadtype AKA Bacon Burger and Whole Wheat.
Does that make sense?
I would use the dreaded Lookup function for this:
http://technet.microsoft.com/en-us/library/ee210531.aspx
I say dreaded because it is notoriously tricky to code and debug. I've even seen a case where a failed Lookup caused the entire row to disappear!
The Lookup target dataset itself should not use the parameters required for the Lookup - it's purpose is to return all the possible rows needed by the Lookup function.
If you need to use two columns as the key to your lookup, you can concatenate them e.g.
Fields!Burger_Lunch_Type.value & "|" & Fields!ItemID.value
Good luck!