I have SQL Server 2005 Reporting Services. I need to create a report with number of columns that is defined during runtime.
I have a DB table with content like the following:
Person Date Val
----------------------------------------------
Person1 2012-01-03 3
Person2 2012-02-11 5
Person1 2012-02-17 7
Person2 2012-01-19 2
Person2 2012-01-15 4
I have to create a Report like this:
Person Jan 2012 Feb 2012
----------------------------------------------
Person1 3 7
Person2 6 5
In other words, for every Person I have to make sum of all his Value fields for a given month, and put the sum into column corresponding to the month. In the example above I have 6 for Person2 during month Jan 2012 - this is sum of the values 2 (on 2012-01-19) and 4 (on 2012-01-15).
Thus, in design time I do not know the date range covered by that my table. I should detect it, to build array of months covered by the date range (the Jan 2012 and Feb 2012 in the sampel above) and add a column for each of the months.
How should I implement this using SSRS?
In SQL 2008 and later the approach to this problem changed a little bit, so make sure that you are looking at reference materials for 2005 if that is what you are using.
On this page, look for the Matrix section. Matrices in SSRS are designed to solve exactly the problem you describe with minimal effort. In 2008 Matrices and Tables are both variants of the "Tablix:" a control that can have both row and column groups.
If you're stuck with Tablix, here's a similar situation that I have solved, How do i represent an unknown number of columns in SSRS?.
Related
I’m building a report in Visual Studio 2017 (SSRS) and it uses a stored procedure that returns the following data:
PRODUCT_ID TYPE YEAR STATUS
15242 01 1516 ACTIVE
54541 02 1617 ACTIVE
64454 01 1516 INACTIVE
73697 02 1516 INACTIVE
98878 03 1617 ACTIVE
I needed to get the counts per status, per year, per type, so I started building a matrix with STATUS as first column group and YEAR as its child, then, in the row group I only have TYPE. In the data fields I only have the count, so it looks like this:
ACTIVE INACTIVE
1516 1617 1516 1617
01 1 0 1 0
02 0 1 1 0
03 0 1 0 0
My problem is the following. I want add a DIFF column (example below) that calculates the difference between the two years, but the problem is that since all is done dynamically, I don’t know how to access the text boxes with the counts to calculate the difference. I could build a stored procedure that calculates all those numbers, but it would be a slower solution since the field TYPE will grow over time.
ACTIVE INACTIVE
1516 1617 DIFF 1516 1617 DIFF
01 1 0 1 1 0 1
02 0 1 1 1 0 1
03 0 1 1 0 0 0
Any help will be appreciated. Thank you guys in advance.
I don't think you'll be able to make a matrix work the way you want without using a bunch of LookUps that would kill performance.
I would make a regular table and filter the data in the expression to separate the years. You'll have to figure out some logic based on your data to determine which year is the current and which is the last year.
You would use the same grouping for the TYPE as you do now.
Assumeing you have identified the previous can current year:
=SUM(IIF(Fields!YEAR.Value = Parameter!Current_Year.Value, 1, 0)
For the DIFF column, use
=SUM(IIF(Fields!YEAR.Value = Parameter!Current_Year.Value, 1, 0) - SUM(IIF(Fields!YEAR.Value = Parameter!Previous_Year.Value, 1, 0)
You could use a variable or a Field in your query to identify the current year - it doesn't need to be a parameter.
You could still use the matrix for your Statuses (Stati?) for the Active and Inactive.
I have found a way to calculate differences between matrix columns (available from SSRS 2008 and up) using the previous function. Look at my answer to this question. how to subtract adjacent columns in an ssrs matrix
how to subtract adjacent columns in an ssrs matrix
I have a SQL Server Report Builder tablix report that evaluates sales activity over time.
Rows by company, columns are grouped by date. Something like this:
2015 2016 2017
Company1 10 12 1
Company2 6 5 0
Company3 8 10 7
(The report also expands columns into months)
I would like to add a column, or color a background, calculated based on the average of each year's totals. For example, Company1 averages 7.6/year if I include 2017. I would like to be able to say that 2015 was 131% of average, 2016 was 157% of average, and 2017 is 13% of average. Bonus points if I can exclude the current year from the average.
The result might look something like this:
2015 2016 2017
Company1 10 (131%) 12 (157%) 1 (7.6%)
Company2 6 (%%) 5 (%%) 0 (%%)
Company3 8 (%%) 10 (%%) 7 (%%)
Since the source data has one sale per row, and the tablix is what's creating the grouped count by date, I can't seem to just run an average, which just gives me "1", due to the fact that I'm counting on a count column. The source data looks something like this:
CompanyName Date SalesRep Amt Count
Company1, 1/1/2015, salesrepname, 50000, 1
Company1, 2/1/2015, salesrepname, 20000, 1
Company1, 3/1/2015, salesrepname, 50000, 1
Company1, 4/1/2015, salesrepname, 10000, 1
Company1, 5/1/2015, salesrepname, 5000, 1
...
How do I go about getting the average of each year?
If you were just grouping on Company and Year you could override the scope of your aggregates with a group name. However, SSRS doesn't have a way to specify combinations of groups. So in your case you will need to make those sub-calculations available another way. It is usually best to do that in the SQL. You can either add a subquery to your existing query (preferred) or add an additional dataset. If you use a separate dataset you'll also have to match up the values with a Lookup function.
If you try to come up with an elaborate workaround like custom code or referencing textboxes it is going to become difficult to maintain and will be very inefficient.
wouldn't a formula like this work?
=sum(Fields!count.Value)/
(sum(Fields!count.Value,"Year")/countdistinct(Fields!CompanyName.Value,"Year"))
assuming your column group name is Year.
at the moment I have two tables. I have one table that displays loan summaries.
Loan Client Balance
11 Bob 100000
20 Steven 100000
33 Michael 100000
I need to enhance this table by adding Loan.Notes
Loan Client Balance
11 Bob 50000
2015-05-06 - Bob came into the office and said we should expect late payments
20 Steven 100000
2015-05-06 - Steven came into the office and he will pay this friday
2015-05-06 - Steven came into the office and said we should expect late payments
33 Michael 700000
The Notes section has two columns, Date of note and the Note.Subject. May I ask how do I add in the notes section onto the tablix?
First you need to create the query joining Loan with the 'LoanNotes'.
In your main table group by Loan. In the header of that group show Loan #, client and balance.
In the Detail section based on your requirements merge the column and show the Notes Data. In the following case I merged three columns and created a expression as =Fields!NoteDate.Value & " - " & Fields!Subject.Value
Now when you run the report you will get the data as you want.
Optional: In the case where there is no note you will need to write an expression in visibility tab to hide your detail row
=IIF(CountRows("LoanGroup") = 1, True, False)
OR
=CountRows("LoanGroup") = 1
The best approach for this is to combine the tables into one datatable joining on a similar key.
You can join the tables in your dbms by using queries to create a new view. or you could use this DataSet JOIN Helper.
You can then group in your Tablix as you see fit.
Another solution would be to add multiple DataSets within the same report.
Using multiple datasets in RDLC
I have a database that tracks invoice payment certification. I am trying to build a report that will bring The following info in
Service Line - ABC
Total "unique" records - 2
max age - 3
Min age - 1
Avg of max age - 3
count of records over 14 days - 0
count of records under 14 days - 2
score: records under 14 days/total records - 100%
I am trying to build the report from a query that includes a date range. the important column names are:
Service Line DLN Age in days
ABC 123456 1
DEF 987654 3
ABC 123456 2
DEF 987654 4
ABC 123456 3
The DLN is an identifier to each different invoice number. I entered the data in above that I need it to return as it correlates to the table below.
I totally forgot I asked the question on here and ended up fixing the issue. What I ended up doing is building the report from scratch from the query instead of using the wizard. Then I just free typed the functions into unbound text boxes. I did then use the grouping to separate it the way I needed. Once I realized my mistake and that the solution was so easy I felt kind of dumb.
compliment of the day.
Based on the previous feedback received,
After creating a Ticket sales database in MS Access. I want to use a single form to Query the price of a particular ticket at a particular month and have the price displayed back in the form in a text field or label.
Below are sample tables and used query
CompanyTable
CompID CompName
A Ann
B Bahn
C Can
KK Seven
- --
TicketTable
TicketCode TicketDes
10 Two people
11 Monthly
12 Weekend
14 Daily
TicketPriceTable
ID TicketCode Price ValidFrom
1 10 $35.50 8/1/2010
2 10 $38.50 8/1/2011
3 11 $20.50 8/1/2010
4 11 $25.00 11/1/2011
5 12 $50.50 12/1/2010
6 12 $60.50 1/1/2011
7 14 $15.50 2/1/2010
8 14 $19.00 3/1/2011
9 10 $40.50 4/1/2012
Used query:
SELECT TicketPriceTable.Price
FROM TicketPriceTable
WHERE (((TicketPriceTable.ValidFrom)=[DATE01]) AND ((TicketPriceTable.TicketCode)=[TCODE01]));
In MS Access, a mini boxes pops up to enter the parameters when running the query. How can I use a single form to enter the parameters for [DATE01] and [TCODE01]. and the price displayed in the same form in a textfield (For further calculations).
Such as 'Month' field equals to input to [DATE01] parameter
'Ticket Code' equals to input for [TCODE01] parameter
Textfield equals to output of the query result (Ticket price)
If possible, I would like to use only the Month and Year in this format MM/YYYY.The day is not necessarry. How can I achieve it in MS Access?
If any question, please don't hesitate to ask
Thanks very much for your time and anticipated feedback.
You can refer to the values in the form fields by using expressions like: [Forms]![NameOfTheForm]![NameOfTheField]
Entering up to 300 different types of tickets
Answer to your comment referring to Accessing data from a ticket database, based on months in MS Access)
You can use Cartesian products to create a lot of records. If you select two tables in a query but do not join them, the result is a Cartesian product, which means that every record from one table is combined with every record from the other.
Let's add a new table called MonthTable
MonthNr MonthName
1 January
2 February
3 March
... ...
Now if you combine this table containing 12 records with your TicketTable containing 4 records, you will get a result containing 48 records
SELECT M.MonthNr, M.MonthName, T.TicketCode, T.TicketDes
FROM MonthTable M, TicketTable T
ORDER BY M.MonthNr, T.TicketCode
You get something like this
MonthNr MonthName TicketCode TicketDes
1 January 10 Two people
1 January 11 Monthly
1 January 12 Weekend
1 January 14 Daily
2 February 10 Two people
2 February 11 Monthly
2 February 12 Weekend
2 February 14 Daily
3 March 10 Two people
3 March 11 Monthly
3 March 12 Weekend
3 March 14 Daily
... ... ... ...
You can also get the price actually valid for a ticket type like this
SELECT TicketCode, Price, ActualPeriod AS ValidFrom
FROM (SELECT TicketCode, MAX(ValidFrom) AS ActualPeriod
FROM TicketPriceTable
WHERE ValidFrom <= Date
GROUP BY TicketCode) X
INNER JOIN TicketPriceTable T
ON X.TicketCode = T.TicketCode AND X.ActualPeriod=T.ValidFrom
The WHERE ValidFrom <= Date is in case that you entered future prices.
Here the subquery selects the actually valid period, i.e. the ValidFrom that applies for each TicketCode. If you find sub-selects a bit confusing, you can also store them as query in Access or as view in MySQL and base a subsequent query on them. This has the advantage that you can create them in the query designer.
Consider not creating all your 300 records physically, but just getting them dynamically from a Cartesian product.
I let you put all the pieces together now.
In Access Forms you can set the RecordSource to be a query, not only a table. This can be either the name of a stored query or a SQL statement. This allows you to have controls bound to different tables through this query.
You can also place subforms on the main form that are bound to other tables than the main form.
You can also display the result of an expression in a TextBox by setting the ControlSource to an expression by starting with an equal sign
=DLookUp("Price", "TicketPriceTable", "TicketCode=" & Me!cboTicketCode.Value)
You can set the Format of a TextBox to MM\/yyyy or use the format function
s = Format$(Now, "MM\/yyyy")