I'm trying to write a query that will calculate "Shares short" divided by "Shares floating". See my table below. I've tried the following expression, but I just get a big fat error.
Expr1: [Shares]![SharesType]="Shares short"/[Shares]![SharesType]="Shares floating"
I've also tried looking at Microsoft's expression tutorials (and the linked tutorials) but they're too general.
I find expression builder more confusing than helpful and don't use it.
If you are trying to do an aggregate query, click the Sigma icon on query designer tab and build in the design grid. Switch to SQL view to view statement which should be like:
SELECT CompanyID, Sum(IIf([SharesType]="s",[Shares],Null))/Sum(IIf([SharesType]="f",[Shares],Null)) AS Expr1
FROM Shares
GROUP BY CompanyID;
This worked.
SELECT Companies.CompanyName, Sum(IIf([SharesType]="Shares short",[Shares],Null))/Sum(IIf([SharesType]="Shares floating",[Shares],Null)) AS [Short as % of Float]
FROM Companies INNER JOIN Shares ON Companies.CompanyID = Shares.[Company ID]
GROUP BY Companies.CompanyName;
So my report now looks like this.
Related
I haven't really worked with SSRS Matrix reports and I'm not sure if what I am trying to do is even possible.
The user can enter a begin and end year. They want the ability to group on either CBA, CRA or Client. The CBA and CRA choice would subtotal after each name, but the client would not. The columns to include would remain the same for each choice. However, they want whatever is grouped by to be moved to the front of the report. If you choose CBA, the columns relating to CBA should appear first. If you choose client, the columns relating to client should appear first.
Is any of this possible with a matrix report? If so, where do I start? Should any of this be done in the stored procedure or should it all be done in Visual Studio? I am using Visual Studio 2017. Below is a sample of what the output should look like.
Any help is greatly appreciated.
report sample
This is certainly possible. There are several ways to do this and you will have to choose how much of it is done in your dataset query/stored proc and how much is done via SSRS expressions.
There are a few things to think about no matter what route you decide on.
Your dataset query or stored proc must always return a dataset that has the same column names with the same datatypes and in the same order
Avoid hiding columns in the report designer as this does not work well
If the dataset returns lots of rows then you might want to do some of the work in the query
The SSRS Way:
If you wanted to do this entirely in the report designer, all the affected columns and groups would need to be set as expressions. For example, in a simplified version of your report, the second column expression would be something like.
=SWITCH(
Parameters!myParam.Value = "CBA", Fields!CBAName.Value,
Parameters!myParam.Value = "CRA", Fields!CRAName.Value,
Parameters!myParam.Value = "Client", Fields!ClientName.Value
)
The Columns header would also have to be a similar expression.
=SWITCH(
Parameters!myParam.Value = "CBA", "CBA Name",
Parameters!myParam.Value = "CRA", "CRA Name",
Parameters!myParam.Value = "Client", "Client Name"
)
The Row Group total (in grey on your example) would also have to be a similar expression.
You would have to repeat this for all affected columns.
Next
You would also need to change the RowGroups in a similar fashion. So you would add a row group and then the "Group On" and "Sort By" expressions to the same thing.
=SWITCH(
Parameters!myParam.Value = "CBA", Fields!CBAName.Value,
Parameters!myParam.Value = "CRA", Fields!CRAName.Value,
Parameters!myParam.Value = "Client", Fields!ClientName.Value
)
It's quite a long winded process but it's not actually that bad to do.
The SQL Method
The idea is basically the same, based on the parameter we pass in, we swap out the columns in the results but we alias them so they look the same in the SSRS dataset. We also have to provide the text for the column headers in the results so we don't have to work it out in the report designer.
Here's a very simple example.
SELECT
CASE #myParam
WHEN 'CBA' THEN CBAName
WHEN 'CRA' THEN CRAName
WHEN 'Client' THEN ClientName
END AS ColumnAValue
CASE #myParam
WHEN 'CBA' THEN 'CBA Name'
WHEN 'CRA' THEN 'CRA Name '
WHEN 'Client' THEN 'Client Name'
END AS ColumnACaption
, *
FROM myTable
Here we are swapping out the content of ColumnAValue and ColumnACaption. In the report designer, we would display ColumnAValue and set the Column Header expression to
=FIRST(Fields!ColumnAHeader.Value)
The Row Groups would both simply sort by ColumnAValue
This method means a lot less work in the report designer.
There are other options but these two methods I what I usually go for as they are the simplest. The SQL method is easier for other developers to understand because there is not much 'hidden' such at the row groups sorting and grouping properties.
At the end of the day it's down to you to decide what you feel comfortable with but hopefully this gives you enough to start.
I downloaded a record of all the people on the first fleet from this website. http://firstfleet.uow.edu.au/download.html
I downloaded the Excel and imported it into Access. In the document, certain people’s age is not known so they are simply put as -1.
I am trying to make this table but I am struggling.
I’ve tried doing it by creating a table but that was too hard so I decided to create a query instead. I am using “Crosstab” but failing to use it successfully.
When I do try to sub the -1 for unknown:
Messages like this pop up:
How do we add the table in but sub the -1 for unknown while keeping the layout the same? I am hard stuck at a place where I cannot even view how my query looks.
How do I even make the layout the same as the picture shown above?
UPDATE:
Calculate the age groups with Switch() function and use that calculated field for CROSSTAB RowColumn. I renamed the Age field in table from the original import name to shorten the expression.
TRANSFORM Count(Convicts.ID) AS CountOfID
SELECT Switch([Age]=-1,"Unknown",[Age]<15,"10-14",[Age]<20,"15-19",[Age]<25,"20-24",[Age]<30,"25-29",[Age]<35,"30-34",[Age]<40,"35-39",[Age]<45,"40-44",[Age]<50,"45-49",[Age]<60,"50-59",[Age]<100,"60-99") AS AgeGrp
FROM Convicts
GROUP BY Switch([Age]=-1,"Unknown",[Age]<15,"10-14",[Age]<20,"15-19",[Age]<25,"20-24",[Age]<30,"25-29",[Age]<35,"30-34",[Age]<40,"35-39",[Age]<45,"40-44",[Age]<50,"45-49",[Age]<60,"50-59",[Age]<100,"60-99")
PIVOT Convicts.Gender;
The total row is added by clicking the Sigma(Totals) icon on the ribbon when query is in Datasheet view.
A simpler calculation will generate more groups:
TRANSFORM Count(Convicts.ID) AS CountOfID
SELECT Partition([Age],0,100,5) AS AgeGrp
FROM Convicts
GROUP BY Partition([Age],0,100,5)
PIVOT Convicts.Gender;
But a little adjustment to the SELECT clause will get same output as the first:
SELECT IIf([Age]=-1,"Unknown",IIf([Age]<50,Partition([Age],0,50,5),IIf([Age]<60,"50:59","60:99"))) AS AgeGrp
Could add a field in table and use one of those expressions in UPDATE action SQL to add calculated AgeGrp, which would simplify the CROSSTAB and other queries needing that group identifier.
I'm New to SSRS.
Im trying to create a report where i need to group by [DATA Flag] column which is working fine ,but once the data is grouped i need to set the DATA FLAG ="TotalCancellations" and there is another column CancellDays which i need to set it as <120 .
I tried
Option 1:-
So to achieve this i have added TWO filters one with
Expression : DATA FLAG
Operator =
and Value as TotalCancellations
and the other filter as follows
Expression : Cancelldays
Operator =
and Value as < 120
But its not working and giving empty result,i have records with Cancelldays <120
Option 2 :-
Right click on Group and in General Tab ,Group on Expression as below ]
Fields!DFlag.Value = "TotalCancellations" AND Fields!DFlag.Value <120
which didnt work :(
this is similar to writing having clause in SQL i believe but im not getting how to implement that here in SSRS.
i can add in SQL Query but its already a huge query with lot of unions so please suggest me if there is any way i can implement here in SSRS
Im using Matrix in SSRS 2008
Adjusting the syntax for your option 1 is probably the easiest solution. In the Group Properties, under the Filters section, enter these two filters:
Expression: [DFlag] (Text)
Operator: =
Value = TotalCancellations
Expression: =Sum(Fields!CancelDays.Value) [enter this in the expression builder] (Integer)
Operator: <
Value: 120
Putting all the filters in a single expression, like your option 2, can be useful if you need to filter by one criteria OR another.
Below are the filer expressions
and this is how group by is
The filter should be implemented at the tablix level, not at the group level.
As a bit of a preface here, I use Access at work, I'm mostly self-taught and I know very little code (if I look at the code, can usually figure out what it does, sometimes I can mimic it).
I've built a crosstab query for handling a summary of all material types since 2009. I had to do some fiddling to get it to sort by month and year, but after finally getting that working, any report I run now pops the error:
"The Microsoft Access Database Engine does not recognize '[Pit Tickets].[Ticket #]' as a valid field name or expression."
Now, I've done some research on this and could only find examples where this error crops up because someone actually USED the field. In this case, the [Ticket #] field isn't even referenced in my query, so I'm not sure why a report based off that query would be giving me an error about it.
Query Code:
TRANSFORM Sum([PitTickets].Quantity) AS SumOfQuantity
SELECT Year([Date]) AS [Year], Month([Date]) AS [Month No], [Pit Tickets].[Ticket Type], Format$([Pit Tickets].[Date],'mmmm yyyy') AS [Date], Sum([Pit Tickets].Quantity) AS [Total of Quantity]
FROM [Pit Tickets]
GROUP BY Year([Date]), Month([Date]), [Pit Tickets].[Ticket Type], Format$([Pit Tickets].[Date],'mmmm yyyy')
ORDER BY Year([Date]), Month([Date])
PIVOT [Pit Tickets].Material;
I have been scratching my head about this since yesterday, can anyone tell me how to fix it?
Have a look at the property sheet for the query to see if there was an Order By or Filter added at some stage. You could also cut and paste the SQL into a new query window and check if you get the same problem.
I'm trying to build a query (QueryB) for it to be referenced in my MS Access control. I know I got the source expression syntax right, I have a very similar working control with QueryA.
I only changed the field and query names. However I keep getting the infamous #Name? error with QueryB. The difference between QueryA and QueryB is the SQL code. QueryA has a GROUP BY and SUM() and QueryB only has DATEDIFF(). I have tried adding the GROUP BY to QueryB, but kept getting [...execute query does not include the specified expression as part of aggregate function].
Query B:
SELECT IIF(DATEDIFF("d",Date_X,Date_Y)>100),
ROUND(IIF(DATEDIFF("d",Date_X,Date_Y)/30,2),
DATEDIFF("d",Date_X,Date_Y)
AS DATEDIFF_X_Y
FROM LAB_DATES GROUP BY LAB_DATES.ID;
This is in MS Access SQL.
ControlB source referencing QueryB in MS Access:
=DLookUp("[DATE_DIFF_X_Y]",
"[QueryB]",
"[LAB_DATES.ID] = " & [Forms]![Lab Results Form]![Textbox_DATE_ID])
When taking out the GROUP BY, this query runs fine but I get the #Name? error in the control. All data is from ODBC MySQL. Access is the front end.
Edit: I can just drop GROUP BY. But I will get the #Name? error. My goal is to display the date difference between Date_X and Date_Y.
[...execute query does not include the specified expression as part
of aggregate function]
That error message already indicates that using GROUP BY does not work with aggregate Functions.
DATEDIFF() is an aggregate function and does not work with a GROUP BY.
The reason for that is that GROUP BY reduces your dataresult and only displays one line per different entry of the column you are using.
What is your aim for that query anyways? I am sure there is a different solumtion for that problem. GROUP BY DATE.ID sounds like you are making a GROUP BY on the primary key which has no effect, because primary keys are unique per definition.
I think your problem is within your DLookup rather than your query. You do not need the GROUP BY at all, this will cause the query to error, you can simply make QueryB:
SELECT IIF(DATEDIFF("d",Date_X,Date_Y)>100),
ROUND(IIF(DATEDIFF("d",Date_X,Date_Y)/30,2),
DATEDIFF("d",Date_X,Date_Y) AS DATEDIFF_X_Y
FROM LAB_DATES;
The problem is that in your DLookup you are using:
[LAB_DATES.ID]
Where you actually want
[LAB_DATES].[ID]
i.e. In it's current form you are looking for a column called LAB_DATES.ID rather than a Column called ID in the object LAB_DATES. Changing your DLookup to this:
=DLookUp("[DATE_DIFF_X_Y]",
"[QueryB]",
"[LAB_DATES].[ID] = " & [Forms]![Lab Results Form]![Textbox_DATE_ID])
Should do the trick.