SSRS - How to total a row - reporting-services

Report Month Booked Month Hours Available Hours Reported Hours
2015-12-01 00:00:00 2015-10-01 00:00:00 3.5 97 172
2015-12-01 00:00:00 2015-10-01 00:00:00 0.75 97 172
2015-12-01 00:00:00 2015-10-01 00:00:00 6.85 97 172
2015-12-01 00:00:00 2015-10-01 00:00:00 3 97 172
2015-11-01 00:00:00 2015-10-01 00:00:00 3.5 97 185
2015-11-01 00:00:00 2015-10-01 00:00:00 0.75 97 185
2015-11-01 00:00:00 2015-10-01 00:00:00 6.85 97 185
2015-11-01 00:00:00 2015-10-01 00:00:00 3 97 185
In my SSRS report i want to total the Reported Hours Column. This person booked 172 hours in December and 185 hours in November so his total for the year should be 185 + 172 = 357.
In my current report it adds together all the rows. How do i get it to just pick one row of reported hours per month?
Thanks

There's not a set way to do this in SSRS.
Usually you would wrap your query in another query that uses ROW_NUMBER and group by months. Then only add the hours if the row_numnber = 1.
How do I use ROW_NUMBER()?
Unfortunately that's not always possible. I wrote some code to add up unique records based on another field. I made it to get check amounts for various vendors.
For the expression, you would use:
=Code.SUMVendors(Report_Month & "|" & Fields!Reported_Hours.Value)
Add the Visual BASIC to the CODE of the report:
FUNCTION SUMVendors(BYVAL ITEMS AS OBJECT()) AS DECIMAL
'Returns Sum of unique vendors. Use as Code.SUMVendors(Vendor & "|" & Amount)
IF ITEMS IS NOTHING THEN
RETURN NOTHING
GOTO EXITSUB
END IF
DIM TEMP AS STRING
DIM VENDORS AS STRING = ""
DIM VENDOR AS STRING = ""
DIM VALUE AS DECIMAL
FOR EACH ITEM AS OBJECT IN ITEMS
TEMP = CONVERT.TOSTRING(ITEM)
VENDOR = "|" & LEFT(TEMP, InStr(TEMP, "|"))
VALUE = CDEC(MID(TEMP, InStr(TEMP, "|") + 1, LEN(TEMP)))
IF InStr(VENDORS, VENDOR) = 0 Then
VENDORS = VENDORS + VENDOR
SUMVendors = SUMVendors + VALUE
End If
NEXT
EXITSUB:
END FUNCTION

Related

Calculate the percentage of success of each measurement values in SQL

I have 3 database tables with sample data given below
Meas_id - integer(Foreign keyed to Measurement.meas_id)
Tool_id - integer(Foreign keyed to Events.Machine_id)
Processdate- Timestamp with timezone (UTC)
CreatedDate- Timestamp with timezone (UTC)
Readings
Meas_id Tool_id Status Processdate
1 13 Completed 2016-01-01 01:34:11
1 28 Failed 2016-01-01 08:37:11
1 54 Failed 2016-01-02 16:04:12
1 32 Completed 2016-01-04 07:13:11
1 39 Completed 2016-01-04 14:14:14
1 12 Completed 2016-01-05 22:10:09
1 9 Completed 2015-12-28 13:11:07
1 17 Completed 2016-01-25 13:14:11
1 27 Completed 2016-01-15 14:15:16
1 31 Failed 2016-01-07 16:08:04
2 113 Completed 2016-01-01 01:34:11
2 128 Failed 2016-01-01 08:37:11
2 154 Failed 2016-01-02 16:04:12
2 132 Completed 2016-01-04 07:13:11
2 139 Completed 2016-01-04 14:14:14
2 112 Completed 2016-01-05 22:10:09
2 90 Completed 2015-12-28 13:11:07
2 117 Completed 2016-01-25 13:14:11
2 127 Completed 2016-01-15 14:15:16
2 131 Failed 2016-01-07 16:08:04
Events
Meas_id Machine_id Event_Name CreatedDate
1 13 Success 2015-12-27 01:34:11
1 17 Error 2015-12-27 08:37:11
1 28 Success 2015-12-27 16:04:12
1 9 Success 2015-12-28 07:13:11
1 54 Success 2015-12-28 14:14:14
1 31 Error 2015-12-28 22:10:09
1 32 Success 2015-12-29 13:11:07
1 39 Success 2015-12-29 13:14:11
1 12 Success 2015-12-31 14:15:16
1 27 Success 2016-01-01 16:08:04
2 113 Success 2015-12-27 01:34:11
2 117 Error 2015-12-27 08:37:11
2 128 Success 2015-12-27 16:04:12
2 90 Success 2015-12-28 07:13:11
2 154 Success 2015-12-28 14:14:14
2 131 Error 2015-12-28 22:10:09
2 132 Success 2015-12-29 13:11:07
2 139 Success 2015-12-29 13:14:11
2 112 Success 2015-12-31 14:15:16
2 127 Success 2016-01-01 16:08:04
Mesurement
Meas_id Meas_name
1 Length
2 Breadth
For each measurement ‘length’ and ‘breadth’ and each day of the week, I am trying to calculate the percentage of success in the first week of 2016 for all completed measurements of tools/machines within 168 hours of thier creation date.
My Desired Output is
Measurement DayofTheWeek PercentageSuccess
Length 1 50
Length 2 0
Length 3 0
Length 4 100
Length 5 100
Length 6 0
Length 7 0
Breadth 1 50
Breadth 2 0
Breadth 3 0
Breadth 4 100
Breadth 5 100
Breadth 6 0
Breadth 7 0
I tried doing it this way but certainly missing some logic and its not working.
Select m.Meas_name,
datepart(dd, Processdate) as DayofTheWeek,
(Count(m.Meas_name)* 100 / (Select Count(Event_Name) From Events where Event_Name = 'Success')) as PercentageSuccess
FROM Readings r JOIN
Measurements m
ON r.Meas_id = m.Meas_id
JOIN Events e
ON e.Meas_id = m.Meas_id
WHERE m.Meas_name IN ('Length', 'Breadth') AND
r.Status = 'Completed' AND
e.CreatedDate >= DATEADD(hh, -168, GETDATE())
GROUP BY m.Meas_name, datepart(dd, Processdate);
Kindly provide inputs on an optimized way of achieving it.
Nice I got downvoted for a correct answer probably because my answer wasn't very clear it is kind of hard to explain so here is an edit aimed at your comment and the downvoter (whom I think was just retaliating).
Anyway, Your joining of 3 tables while valid replicates the data in your events table. Due to that the way you are counting the records will always be exaggerated and incorrect. your calculation for percentage is also happens to be backwards.
On the join it looks like you are just missing the use of the Tool_id in your join. You could try something like the following:
SELECT
m.Meas_name
,DAYOFWEEK(r.ProcessDate) as DayOfTheWeek
,(COUNT(CASE WHEN e.Event_Name = 'Success' tHEN e.Meas_id END)/(COUNT(e.Meas_id) * 1.0)) * 100 as PercentageSuccess
FROM
Measurements m
INNER JOIN Events e
ON m.Meas_id = e.Meas_id
INNER JOIN Readings r
ON e.Meas_id = r.Meas_id
AND e.Machine_id = r.Tool_id
AND r.Status = 'Completed'
AND r.ProcessDate BETWEEN '2016-01-01' AND '2016-01-07'
WHERE
m.Meas_name IN ('Length','Breadth')
GROUP BY
m.Meas_name
,DAYOFWEEK(r.ProcessDate)
Note this is written for mysql because that is what is tagged in you post. if you actually want sql-server as your syntax suggests let me know. Also, I am guessing that you a really want to filter by processdate but if you want to filter by Event.CreateDate then put that in the ON condition of the Events join.

How to convert date range into whole number (integer) in SQL

Let's say I have a date 2013-03-01 and date 2013-04-02. How do I get a integer value between that date, for example in this case 2 days. In SQL kindly advise how to construct the query
day_date
---------------------
2005-07-29 00:00:00
2013-03-01 00:00:00
2013-04-02 00:00:00
2013-06-01 00:00:00
2013-10-19 00:00:00
2013-10-23 00:00:00
2013-12-31 00:00:00
The DATEDIFF() function returns the time between two dates.
SELECT DATEDIFF('2014-11-30','2014-11-29') AS DiffDate

Time difference in SQL between two rows

I have a table called eventdata like this
Timestamp GUId EventTypeId
2015-02-01 05:00:00 1100 E012-1
2015-02-01 05:30:00 1100 E012-2
2015-02-01 06:00:00 1100 E012-1
2015-02-01 06:20:00 1100 E012-2
2015-02-01 07:00:00 2200 E012-1
2015-02-01 07:15:00 2200 E012-2
Now corresponding to Guid, we have different EventTypeId. Now when I see E012-2 to corresponding E012-1 for a GUID (this could be different, for example sake I gave like this) I need a difference in Timestamp in minutes.
Example: for first two rows, for GUID=1100 it's 30. For the 3rd and 4th rows it's 20 minutes. for Guid=1100 for 5th and 6th rows it's 15 mints for Guid=2200.
I am using MySQL.

Select specific records and change its values

I have a table filled with (DUTCH) holidays in the past and future and I need to change the name and date for a specific holiday. Since we don't have a Queen anymore, but a King, Queensday is no longer a holiday. Now its Kingsday. AND it is celebrated on a different date.
This is my current table:
68 NL 2014-04-30 Queensday
77 NL 2015-04-30 Queensday
88 NL 2016-04-30 Queensday
97 NL 2017-04-30 Queensday
106 NL 2018-04-30 Queensday
115 NL 2019-04-30 Queensday
124 NL 2020-04-30 Queensday
134 NL 2021-04-30 Queensday
I want to change all records where description='Queensday' into description='Kingsday' AND date=date-3days (since it is celebrated each April 27th) but only where year of the date is greater than 2013.
update table
set
description = 'Kingsday',
<yourdateField> = date_sub(<yourdateField>, interval 3 DAY)
where description = 'Queensday'
and year(<yourdateField>) > 2013
bonus (?)
update country
set
politicalSystem = 'democracy',
comment = 'easier to manage holidays'
where
politicalSystem = 'royalty'

Transposing rows into columns - An Issue faced.

I'm having the following data set (note that my database/schemata is somewhat complex so it's not feasible to include all the details here)
This is a simplified version of my data which I extracted from my base tables and created a view.
workout_activity_record_id attribute_metric_id attribute_metric_value workout_exercise_set_created_on
234 17 10 2012-02-06 00:00:00
234 18 30 2012-02-06 00:00:00
234 17 20 2012-03-03 00:00:00
234 18 12.9 2012-03-03 00:00:00
234 17 20 2012-04-02 00:00:00
234 18 40 2012-04-02 00:00:00
.
.
. (So on for further workout_activity_record_ids)
I need to compute (look up in the data to understand better)
Grand Total = (10 * 30) + (20 * 12.9) + (20 * 40) grouped by month.
A basic approach here that would aid in multiplying is transpose the rows into columns. So the above structure would become -
workout_activity_record_id ex17 ex18 workout_exercise_set_created_on
234 10 30 2012-02-06 00:00:00
234 20 12.9 2012-03-03 00:00:00
234 20 40 2012-04-02 00:00:00
.
.
.
.
. (And so on for remaining workout_activity_record_ids)
For this, I went through several SO posts and after trying out various viable/non-viable (:D) options, I came up with the following query.
SELECT
CASE attribute_metric_id
WHEN '17' THEN attribute_metric_value END AS 'ex17',
CASE attribute_metric_id WHEN '18' THEN attribute_metric_value END AS 'ex18',
workout_exercise_set_created_on
FROM exercise_attribute
WHERE workout_activity_record_id =234
And the actual output I got was
workout_activity_record_id ex17 ex18 workout_exercise_set_created_on
234 10 NULL 2012-02-06 00:00:00
234 NULL 30 2012-02-06 00:00:00
234 20 NULL 2012-03-03 00:00:00
234 NULL 12.9 2012-03-03 00:00:00
234 20 NULL 2012-04-06 00:00:00
234 NULL 40 2012-04-02 00:00:00
Can anyone shed some light over this? I'd be grateful. Thanks!
This computes the grand total for you, grouped by year and month:
SELECT YEAR(workout_exercise_set_created_on) AS YEAR,
MONTH(workout_exercise_set_created_on) AS MONTH,
sum(SubTotal) AS GrandTotal
FROM
(SELECT workout_exercise_set_created_on,
max(CASE WHEN attribute_metric_id = 17 THEN attribute_metric_value END) * max(CASE WHEN attribute_metric_id = 18 THEN attribute_metric_value END) AS SubTotal
FROM MyTable
GROUP BY workout_exercise_set_created_on) a
GROUP BY YEAR(workout_exercise_set_created_on),
MONTH(workout_exercise_set_created_on)
SQL Fiddle Example
Output
YEAR MONTH GRANDTOTAL
2012 2 300
2012 3 258
2012 4 800
Just add aggregate function :
SELECT
MAX(CASE attribute_metric_id
WHEN '17' THEN attribute_metric_value
END) AS 'ex17',
MAX(CASE attribute_metric_id
WHEN '18' THEN attribute_metric_value
END) AS 'ex18',
workout_exercise_set_created_on
FROM exercise_attribute
WHERE workout_activity_record_id =234
GROUP BY workout_exercise_set_created_on
If you need to show results for different workout_activity_record_id you should modify group by workout_activity_record_id,workout_exercise_set_created_on