Totaling an expression in SSRS - reporting-services

I have an expression that calculates a value in a textbox. I would like, at the end of the report, to have a total of all the fields in that textbox. However, the expression uses named fields from the query, which are totaled also.
=SUM(Fields!Total_Defective__.Value) / SUM(Fields!sales_Dollars.Value)
Total_Defective__ and sales_Dollars are totaled at the end of the report. So when I put that expression in the total field for that column, it performs the calculation on the totals for the other columns. This produces a incorrect result, since its based on the totals of the other fields. what I'm trying to do is sum the column. I tried Use a summary field in an expression in SSRS reports but this only gives me the row above the total, and you cannot aggregate by it.
So the report looks like this:
The COQ total colummn is taking the total of Defective $ / sales. I would like it to add the column (COQ) to be $0.39
Here is what the query looks like:
--Prod Qty
SELECT Division as 'division', SUM(prodtable.qtysched)as 'qty',rtrim(Ltrim(itemgroupid)) as 'itemGroup'
into #SCHED
FROM MiscReportTables.dbo.PlantDivisions
inner join prodtable on prodtable.dimension2_ = MiscReportTables.dbo.PlantDivisions.Division
WHERE PlantID IN (#plantid)
and SCHEDDATE between #start and #end
Group by itemgroupid,MiscReportTables.dbo.PlantDivisions.Division
--sales qty
Select Division as 'Division', SUM(SALESQTY) as 'salesQTY',rtrim(Ltrim(salesline.itemgroupid)) as 'itemGroup'
into #salesQty
FROM MiscReportTables.dbo.PlantDivisions
inner join prodtable on prodtable.dimension2_ = MiscReportTables.dbo.PlantDivisions.Division
inner join SalesLine on SalesLine.InventrefId = ProdTable.ProdiD
WHERE PlantID IN (#plantid)
and SCHEDDATE between #start and #end
Group By Division,salesLine.itemgroupid
--SALES Dollars
Select Division as 'Division',
(SUM(SALESQTY) - REMAINSALESFINANCIAL) * (SalesPrice / PriceUnit) as 'sales$',
rtrim(Ltrim(salesline.itemgroupid)) as 'itemGroup'
into #salesDollars
FROM MiscReportTables.dbo.PlantDivisions
inner join prodtable on prodtable.dimension2_ = MiscReportTables.dbo.PlantDivisions.Division
inner join SalesLine on SalesLine.InventrefId = ProdTable.ProdiD
WHERE PlantID IN (#plantid)
and SCHEDDATE between #start and #end
Group By Division,salesLine.itemgroupid,REMAINSALESFINANCIAL,SalesPrice,PriceUnit
SELECT
dbo.TQMNCR.NCRID,
dbo.TQMPlantTable.PlantName AS 'Division',
RTRIM(LTRIM(dbo.INVENTTABLE.ITEMGROUPID)) AS 'Item Process/Group',
dbo.TQMNCRDEFECTTYPECODES.QTY AS 'Defective Qty',
CASE CATYPE
WHEN 0 THEN
(CASE WHEN dbo.SALESLINE.SALESID = ''
THEN ISNULL((PRICE * (PERCENTEXT / 100)) / NULLIF(dbo.INVENTTABLEMODULE.PRICEUNIT, 0), 0) * dbo.TQMNCRDEFECTTYPECODES.QTY
ELSE ISNULL((SALESPRICE * (PERCENTEXT / 100)) / NULLIF(dbo.SALESLINE.PRICEUNIT, 0), 0) * dbo.TQMNCRDEFECTTYPECODES.QTY END)
WHEN 2 THEN
(CASE WHEN dbo.TQMNCR.SALESID = ''
THEN ISNULL((PRICE * (PERCENTINT / 100)) / NULLIF(dbo.INVENTTABLEMODULE.PRICEUNIT, 0), 0) * dbo.TQMNCRDEFECTTYPECODES.QTY
ELSE ISNULL((SALESPRICE * (PERCENTINT / 100)) / NULLIF(dbo.SALESLINE.PRICEUNIT, 0), 0) * dbo.TQMNCRDEFECTTYPECODES.QTY END)
ELSE 0 END AS 'Total Defective $',
dbo.PRODTABLE.PRODPOOLID
,#SCHED.qty,
(#SCHED.qty - dbo.TQMNCRDEFECTTYPECODES.QTY) / #SCHED.qty as 'First Pass Yield',
#salesQty.salesQty as 'Sales Quantity',
#salesDollars.sales$ as 'sales Dollars'
FROM
dbo.TQMNCR LEFT OUTER JOIN
dbo.TQMDISPOSITION ON dbo.TQMNCR.DISPOSITIONID = dbo.TQMDISPOSITION.DISPOSITIONID LEFT OUTER JOIN
dbo.TQMCA_TABLE ON dbo.TQMCA_TABLE.NCRID = dbo.TQMNCR.NCRID LEFT OUTER JOIN
dbo.TQMNCRDEFECTTYPECODES ON dbo.TQMNCR.NCRID = dbo.TQMNCRDEFECTTYPECODES.NCRID LEFT OUTER JOIN
dbo.TQMPlantTable ON TQMPlantTable.PlantID = dbo.TQMNCR.PlantID LEFT OUTER JOIN
dbo.INVENTTABLE ON dbo.TQMNCR.ITEMID = dbo.INVENTTABLE.ITEMID LEFT OUTER JOIN
dbo.INVENTTABLEMODULE ON dbo.INVENTTABLE.ITEMID = dbo.INVENTTABLEMODULE.ITEMID AND MODULETYPE = 2 LEFT OUTER JOIN
dbo.SALESLINE ON dbo.SALESLINE.SALESID = dbo.TQMNCR.SALESID AND dbo.SALESLINE.ITEMID = dbo.TQMNCR.ITEMID LEFT OUTER JOIN
dbo.PRODTABLE ON dbo.TQMNCR.PRODID = dbo.PRODTABLE.PRODID
inner join #sched on #sched.itemGroup = INVENTTABLE.itemgroupid
inner join #salesQty on #salesQty.itemGroup = INVENTTABLE.itemgroupid
inner join #salesDollars on #salesDollars.itemgroup = INVENTTABLE.itemgroupid
WHERE
SCHEDDATE between #start and #end
AND
dbo.TQMNCR.PlantID IN (#plantid)
ORDER BY dbo.INVENTTABLE.ITEMGROUPID, dbo.TQMPlantTable.PlantName
drop table #sched
drop table #SalesQty
drop table #salesDollars
and here's what the result set looks like:
The report is grouped by Item_Process,Division,Total_Defective

You could try adding your COQ field as a new Calculated Field in your dataset. Doing this will perform the calculation at dataset level, rather than Tablix grouping level.
Lets say you've called this new field "COQ".
Then in your total row, have the expression Sum(Fields!COQ.Value) as your total.
This should perform the calculation for each row's COQ first, then sum the result in the total row.
EDIT: The above will work if your dataset were grouped exactly as your table will be. When this is not the case (as you've indicated) and your table in SSRS is actually grouped from a more granular dataset, you can total your groups using the expression below:
=Sum(IIF(Sum(Fields!sales_Dollars.Value,"YOURGROUPNAME") > 0,
Sum(Fields!Total_Defective__.Value,"YOURGROUPNAME") /
Sum(Fields!sales_Dollars.Value,"YOURGROUPNAME"), 0))
This should evaluate the calculation within each member of the GROUP BY, and then SUM the result of the calculation across the entire table/dataset.

I beleive your requirement is beyond the capabilities of SSRS alone. I would move the grouping to the SQL dataset and (after grouping to the 9 "detail" rows in your example) I would calculate COQ in that dataset e.g.
SELECT *
, Total_Defective / Sales AS COQ
FROM (
SELECT
MyGroupColumns
, SUM ( Total_Defective ) AS Total_Defective
, SUM ( Sales ) AS Sales
FROM MyTable
GROUP BY
MyGroupColumns
) D1
Then SSRS can just present the detail COQ for the 9 rows output from the dataset, and you can use an SSRS Sum() function to get COQ for your Total row.

You should be able to do this with
=SUM(Fields!Total_Defective__.Value/Fields!sales_Dollars.Value)
So that it divides each value, then sums rather than summing the values before dividing.
EDIT: if you get divide by zero errors you can add the following to Report - Report Properties - code:
Public Function Quotient(ByVal numerator As Decimal, denominator As Decimal) As Decimal
If denominator = 0 Then
Return 0
Else
Return numerator / denominator
End If
End Function
(Ref: http://williameduardo.com/development/ssrs/ssrs-divide-by-zero-error/)
The enter the formula as
=SUM(code.Quotient(Fields!Total_Defective__.Value,Fields!sales_Dollars.Value)
Then you should get the desired result with relatively short code in your expression.

Related

List ReportServer parameters for Report that run more that some average execution time

i am trying to get report parameters from ReportServer.dbo.Catalog table for reports that run more than average time of execution. So far i can calculate min.max,avg time of execution, but i am looking to check reports parameters that runs more then some average time.
SELECT TOP 100
COUNT(*) TimesRun,
c.[Name] ReportName,
AVG(l.TimeDataRetrieval + l.TimeProcessing + l.TimeRendering) / 1000.0 [AverageExecutionTimeSeconds]
FROM [ReportServer].[dbo].[ExecutionLog](NOLOCK) AS l
INNER JOIN [ReportServer].[dbo].[Catalog](NOLOCK) AS c ON l.ReportID = C.ItemID
WHERE c.Type = 2 -- Only show reports 1=folder, 2=Report, 3=Resource, 4=Linked Report, 5=Data Source
GROUP BY c.Name
HAVING AVG(l.TimeDataRetrieval + l.TimeProcessing + l.TimeRendering) / 1000.0 > 1
ORDER BY AVG(l.TimeDataRetrieval + l.TimeProcessing + l.TimeRendering) DESC;
How to combine this code , maybe like a stored procedure to get avg value for each report and also check what parameters were used when report exceeded avg value.
It depends on what you are trying to do with the data and how you expect the output to look.
You could do something simple like CROSS APPLY a split function over the parameters column. Something like this will give you the parameters split over rows. It may not be what you need but hopefully will point you in the right direction.
SELECT TOP 100
COUNT(*) TimesRun,
c.[Name] ReportName,
AVG(l.TimeDataRetrieval + l.TimeProcessing + l.TimeRendering) / 1000.0 [AverageExecutionTimeSeconds]
, p.[value] AS ParameterNameAndValue
FROM [ReportServer].[dbo].[ExecutionLog](NOLOCK) AS l
INNER JOIN [ReportServer].[dbo].[Catalog](NOLOCK) AS c ON l.ReportID = C.ItemID
CROSS APPLY string_split(CAST(Parameters as varchar(max)),'&') p
WHERE c.Type = 2 -- Only show reports 1=folder, 2=Report, 3=Resource, 4=Linked Report, 5=Data Source
GROUP BY c.Name, p.[value]
HAVING AVG(l.TimeDataRetrieval + l.TimeProcessing + l.TimeRendering) / 1000.0 > 1
ORDER BY AVG(l.TimeDataRetrieval + l.TimeProcessing + l.TimeRendering) DESC
You could further split this into the parameter name and value I'm not sure what you really need.

mysql group by and ratio between two sums

I have a query which sums field 'value' from rows with foreign key value V1 and divides that sum with sum of the field 'value' from rows with foreign key value V2. Somehow I am getting wrong results. What am I doing wrong here?
SELECT
iv1.year,
1,
iv1.country_code,
SUM(iv1.value) / SUM(iv2.value) AS value, # Formula
'Added using stored procedure for creation of 1 indicator as ratio of 2 over 6 indicators' AS additional_info
FROM
indicators_values iv1
JOIN indicators i1 ON (i1.no_of_indicator IN('B1.1.2.3', 'B1.2.2.2')
AND iv1.indicator_id = i1.indicator_id
AND i1.extracted_from_file_type = 'consolidated-a')
JOIN indicators_values iv2 ON (iv2.country_code = iv1.country_code AND iv2.year = iv1.year)
JOIN indicators i2 ON (i2.no_of_indicator IN('B1.1.2.2', 'B1.1.2.3', 'B1.1.2.4', 'B1.2.2.1', 'B1.2.2.2', 'B1.2.2.3')
AND iv2.indicator_id = i2.indicator_id
AND i2.extracted_from_file_type = 'consolidated-a')
WHERE
1=1
AND iv1.country_code = 'AT'
AND i1.no_of_indicator IN('B1.1.2.3', 'B1.2.2.2')
AND i2.no_of_indicator IN('B1.1.2.2', 'B1.1.2.3', 'B1.1.2.4', 'B1.2.2.1', 'B1.2.2.2', 'B1.2.2.3')
GROUP BY
iv1.year, iv1.country_code;
I know that I am getting wrong results, because most of the results that I am getting are bigger than 1, and they should all be smaller than 1, since I should have in the denominator same values contained in the numerator, plus some additional ones. Please advise? Thanks!
Schematically (too lazy to understand your conditions - maybe something is missing or changed places):
SELECT iv.year,
iv.country_code,
( SUM(CASE WHEN i.no_of_indicator IN('B1.1.2.3', 'B1.2.2.2')
THEN iv.value
END)
/
SUM(CASE WHEN i.no_of_indicator IN('B1.1.2.2', 'B1.1.2.3', 'B1.1.2.4', 'B1.2.2.1', 'B1.2.2.2', 'B1.2.2.3')
THEN iv.value
END
) AS value
FROM indicators_values iv
JOIN indicators i ON iv.indicator_id = i.indicator_id
WHERE i.extracted_from_file_type = 'consolidated-a'
AND iv.country_code = 'AT'
GROUP BY iv.year, iv.country_code
PS. Divisor may formally be zero - take care not to get a division by zero error.

Save Conditional sum result in variable MySQL

I am stuck in a query I want to store sum result in a variable where status = 3, what happening right now is it store the value of last row and show it with all rows
Here is the query
SELECT
request_made_on,driver_id,
#sum_result = SUM(status = 3) AS complete_count,#sum_result,
SUM(status = 6) AS missed_count,
(status = 4) AS canceled_count,
sum(actual_fare),sum(discount)
from tb_engagements
group by date(request_made_on),driver_id;
and here is the screenshot,
second screenshot
I'm guessing that you want the sum of all the values:
select request_made_on, driver_id,
(#sum_result := #sum_result + SUM(status = 3)) AS complete_count,
sum(status = 6) AS missed_count,
sum(status = 4) AS canceled_count,
sum(actual_fare),
sum(discount)
from tb_engagements c cross join
(select #sum_result := 0) params
group by date(accept_time), driver_id;
Notes:
You don't need to return the value of the variable as well as the expression. The expression adds a column to the result set with the value.
You don't need if() to count values. MySQL has a nice short-hand, treating boolean expressions as integers in a numeric context.

How to filter multiplication of a value in sql

i want give discount offer for sale if the quantity 2 or its multiplication (2,4,6,8 etc ..) hoe to filter a value with this
my Query is
SELECT OFFER_MASTER0001.offer_type,OFFER_MASTER0001.discount,OFFER_DETAILS0001.offer_itemcode, OFFER_DETAILS0001.offer_qty,OFFER_MASTER0001.item_code
FROM OFFER_MASTER0001
LEFT OUTER JOIN OFFER_DETAILS0001
ON OFFER_MASTER0001.offer_no = OFFER_DETAILS0001.offer_no
WHERE (OFFER_MASTER0001.item_code = '0000010')
AND (OFFER_MASTER0001.qty = 2)
AND (OFFER_MASTER0001.date_from < '06-Mar-15 11:27:38 AM' AND OFFER_MASTER0001.date_to > '06-Mar-15 11:27:38 AM')
Here is quantity = 2, but I need all multiplication amount of the quantity.
Use modulo.
Change
AND (OFFER_MASTER0001.qty = 2)
to
AND (OFFER_MASTER0001.qty % 2 = 0)
The above condition matches all even numbers

Default value 0 to prevent suppression of sub-report

I'm fairly new to ssrs and I'm trying to creat a report with a sub-report which e.g. returns 3 fields / columns.
When I export this to excel it reads
A1 B1 C1
100 50 100
When there's no data / dataset returns no records all cells A to C are merged to one cell?
Which makes processing the file a real pain...
I've tried the norowsmessage but then I get one value in the merged cells.
Can't remember I had this with Crystal Reports?
Is there something I can do to always return the sub-report with the 3 columns in it so my layout is retained?
Thanks in advance,
Mike
I've fixed it by using a Union statement in my SQL string:
SELECT - SUM(QTY) AS EXPR1, - SUM(ENTEREDVALUE) AS EXPR2, - SUM(LINEAMOUNTMST) AS EXPR3
FROM DBS_SUPERVISOR.STOCKTRANS
WHERE (DATASET = 'CAT') AND (ITEMNUMBER = :myitem) AND (DATEPHYSICAL >= :VanDatum) AND (DATEPHYSICAL <= :TotDatum) AND (STREFERENCE = 0) AND
(DCTYPE = 1) AND (STATUSOUTFLOW = 1) AND (DCGROUP = 'GROUPX')
GROUP BY ITEMNUMBER
UNION ALL
SELECT 0 AS EXPR1, 0 AS EXPR2, 0 AS EXPR3
FROM SYS."DUAL"
WHERE (NOT EXISTS
(SELECT QTY AS EXPR1
FROM DBS_SUPERVISOR.STOCKTRANS STOCKTRANS_1
WHERE (DATASET = 'CAT') AND (ITEMNUMBER = :myitem) AND (DATEPHYSICAL >= :VanDatum) AND (DATEPHYSICAL <= :TotDatum) AND (STREFERENCE = 0)
AND (DCTYPE = 1) AND (STATUSOUTFLOW = 1) AND (DCGROUP = 'GROUPX')))
This way if the top part doesn't return a row the bottom part will return 3 columns with 0
Regards,
Mike