In SSRS, can you group multiple parameter values into one? - tsql

I am relatively new to SSRS but have been working with SQL for years. I have been tasked with creating a report that reflects shipped items based on their status. For example, I have x number of items with varying statuses including "IN_TRANSIT", "RECEIVING", "SHIPPED", "WORKING", and "CLOSED". The requestor is asking if I can provide the following options in a report drop down:
"IN_PROCESS" Status filter including all statuses except "CLOSED".
"CLOSED".
Essentially, they want to be able to view all non closed statuses, closed, statuses, or all. Right now, I have it set so you can individually select all statuses, essentially getting them the data they want, just not with the "right" parameters.
My question is, does SSRS provide a way to essentially 'group' the non-closed statuses into one inside the report so that when they select "IN_PROCESS" it sends those non-closed statuses to the SQL query I have built in? The problem with using SQL for this is that the dataset I created to generate the dropdown options provides "CLOSED" and "IN_PROCESS" as it's output options, but when they select "IN_PROCESS" (sending that value to the filter in the report), since it's not an actual status, nothing comes back.
If more information or clarification is required, please let me know.
Thanks ahead of time!

You can create a new column in your SQL query and use a CASE statement to give the value of IN_PROCESS or CLOSED for the applicable status. Then you will just need to the filtering condition to match the SSRS parameter to the new column.

Depending on how often this case is likely to be reused should help determine how to approach it. If it sounds like it might become a regular process.... "Oh can we have another report with the same filter but showing xyz " then take the time to setup correctly and it will save time in the future.
Personally I would add a database table, if possible, that contains the status names and then a status group name (ignoring fully normalising for the sake of simplicity here).
CREATE TABLE StatusGroups(Status varchar(10), StatusGroup varchar(10))
INSERT INTO StatusGroups VALUES
('IN_TRANSIT', 'In Process'),('RECEIVING, 'In Process'),('SHIPPED', 'In Process'),('WORKING', 'In Process'),('CLOSED' 'Closed')
Then a simple view
CREATE MyNewView AS
SELECT t.*, g.StatusGroup
FROM MyTable t
JOIN StatusGroups g on t.STATUS = g.Status
Now change your report dataset query to use this view passing in the report parameter like this...
SELECT *
FROM MyNewView
WHERE StatusGroup = #myReportParameter
Your dataset for your report parameter's available values list could then be something like
SELECT DISTINCT StatusGroup FROM StatusGroups
This way if you every add more status or statusgroup values you can add an entry to this table and everything will work without ever having to edit your report.

Related

Crystal Report create separate report pages based on field value change

Looking for some advice related to data grouping and printing in Crystal Reports.
I'm working with an order confirmation form. Ideally I would create separate report pages based on a specific field value change for the 'warehouse' field. So, if any given line on an order comes from warehouse A, it prints together. Then we'd get a page break, and we'd see the form repeat for any lines coming from warehouse B.
I've inserted a new group for "warehouse" and configured the group as 'New Page Before.' But when I attempt to print I'm getting an error related to "There must be a group that matches this field". So there must be some pre-existing grouping that I'm not considering. I'm hopeful I can figure this out.
I am interested to get thoughts on overall design, and if the grouping approach I am trying to take is even the correct one.
Somewhere in your report you probably have a formula such as:
Sum({some_value}, {some_field})
where the {some_field} used to be -- but is no longer -- grouped upon.
Fix that expression to set the desired aggregation level (the 2nd argument) to a field you are actually grouping on.

How can I use Crystal Reports record selection to choose from a list AND included a specific field

I am trying to figure out how to write a formula in the record selector that would allow me to select records in a specified list....but ONLY if there is also a specific record.
In My example. I am pulling earnings codes for employees from specific payroll transactions. For each Transaction date...each employee will have up to 10 codes.
I have my record selection set as this to narrow down the codes I want to see:
{UPCHKD.EARNDED} in ["01", "02", "BNSQT", "BVMT", "CASHBO", "FLAT", "HOL", "HOLPAY", "WAPFML"]
The issue is that I only want to see the first 8 codes IF there is also the WAPFML code. I can't figure out how to tell the record Selector to pick records that have BOTH WAPFML and any of those other 8 codes.
{UPCHKD.EARNDED} in ["01", "02","BNSQT", "BVMT", "CASHBO", "FLAT", "HOL", "HOLPAY", "WAPFML"] and
{UPCHKH.TRANSDATE} in {?Beginning Check Date} to {?Ending Check Date}
I hoped to see only checks where the WAPFML code existed. But I'm obviously returning checks that may not have that code. Using Group selection doesn't work as then I don't see the lines for the other codes.
Assuming you are grouping on {Employee_ID}, Add a group selection formula of MAX({UPCHKD.EARNDED}, {Employee_ID} ) = "WAPFML"
This takes advantage of the fact that "WAPFML" happens to be the largest alpha value in the set. If that is not the case, a more robust approach is to add the UPCHKD table a second time (with an alias), join on same Emp_ID to the first alias, and add a record selection condition on the 2nd alias forcing it to be "WAPFML"
OH I GOT IT! I was grouping by Employee and then transaction date. I entered Maximum ({UPCHKD.EARNDED}, {UPCHKH.TRANSDATE}) = "WAPFML" and took maximum of each transaction date and BOOM. Which now makes all the sense in the world. Thanks so much MilletSoftware for helping me!

Consolidate rows in report

If a row has the same ID as the last one, I want to combine them - summing up the cubicFt and Savings. $perFt divides the savings by the cubicFt, so it wouldn't be summed, simply dividing the new results. I also want the Descriptions to be concatenated, like this:
Make a Group based on ID (or whatever the leftmost column is). Then suppress the Details section and the Group Header. Instead, you'll be putting all the fields you want to display in the Group Footer. From there it's simple:
Create a Summary or Running Total for both cubicFt and Savings.
Reconfigure your $PerFt to use the summary/running total fields you made in step 1.
Combine the Descriptions by creating a shared string variable Descriptions. Whenever the group changes, reset it with Descriptions = "". Whenever the group doesn't change, add the description string to your variable. Something like:
Descriptions = Descriptions & " ; " & {yourtable.Description}
Then create a final formula ShowDescription in the Group Footer to display the results with RIGHT(Descriptions, LEN(Descriptions)-2)
You need to do grouping, either by modifying the SELECT statement or the stored query that generates the data, or within Crystal Reports. I'm literally 20 years out of date on Crystal Reports, although I have used similar software, so this will have to be tweaked.
For the first solution, all you need is a concatenation aggregation function for the string field. Your DB may or may not have one built in, so you may need to add it.
SELECT Building, ID,
SUM(cubicFt), SUM(savings),
SUM(savings)/SUM(cubicFt) AS [$perft],
LEFT(STRING_AGG(description, ';'), -1) -- drop extra ; at end
GROUP BY Building, ID;
However, you should be able to do the same within Crystal by setting this up as a subtotal group (not sure if you have to do user definitions for the string aggregation), and then hiding the detail section.

SSRS 2008 limiting scope based on expression

I have a fairly simple problem, but I don't think I understand SSRS and scopes well enough to figure this out.
What I have is a case (one entity) that can have multiple appointments (another entity). Appointments have a date and a status. I want to display the next soonest appointment date and its status. To display the date I'm using
=Min(IIf(Fields!appt_start.Value > Globals!ExecutionTime, Fields!appt_start.Value, Nothing))
The idea is that I first pick only those appointments that occur in the future, and then grab the soonest one. It seems to work great.
Now, I need to apply the same filtering logic, but display the appointment status rather than the date. From my understanding, this is where scopes would come in. I could limit my scope to just the appointment I want, and then show its status. But I don't understand how to do that.
One way to go about this particular problem would be to use a filter in combination with the First function. Add a filter to the table to only show dates greater than the current day. Use a table row with no grouping and use expressions like this:
=First(Fields!appt_start.Value)
=First(Fields!appt_status.Value)
Another option would be to add calculated fields to the dataset to only populate values such as status when the date is greater than the current day. This is useful if you need to show more information later on.
Edit: Yes, you would want to sort the data by date for the First function to work right. You can actually filter at 3 different levels in SSRS. Right-click on your dataset and go to Dataset Properties. Click on Filters. Click Add. Fill in the expression, operator, and value to meet your need. You can also do this in the group properties or the table properties.

Crystal Report show history based only on two field changes

I’m trying to write a report using the history_table.
I want to know how would I only bring the records only to show a history if only two fields have changed ex (ss.dem1) and (ss.dem2) in the table
If anything else changes like phone or address that are in the table as well to not bring that up or suppress it in the report. I want to see the data only those 2 fields have changed and every time it has changed as a history.
This would be an example of what I'm trying to accomplish.
I also used tried to use a suppression formula but only gave me the last record and not show me the example like I would of like above
not onlastrecord and next(PATID)=PATID and next(ssdem1)=ssdem1
or
not onlastrecord and next(PATID)=PATID and next(ssdem2)=ssdem2
Any help is greatly appreciated.
On the DB side you could do a self-join and only keep the records where one of those items you're interested in has changed, ex:
select WHATEVER
from HISTORY H1, HISTORY H2
where H1.PAT_ID=H2.PAT_ID
and (H1.DEM1 <> H2.DEM1
or H1.DEM2 <> H2.DEM2
etc...)
Or, you could order the report by PAT_ID, then by the date/time of the edit and then suppress the rows where nothing changes, which sounds like what you were trying to do. If you post the exact suppression formula I might be able to see where you were going wrong. Should be something like:
not(onfirstrecord) or
({TABLE.PAT_ID}=previous({TABLE.PAT_ID})
and {TABLE.DEM1}=previous({TABLE.DEM1}) //check all fields you're concerned with for equality
and {TABLE.DEM2=previous({TABLE.DEM2})
and etc...)