Calculate Sum in matrix of SSRS report by column value - matrix

The report is designed to display the hours actually worked and the hours an employee should have worked between two specified dates. For this I used a matrix.
The problem is in total row. The actually worked hours are counted correctly, and the hours that the employee should have worked are counted not by the sum of the column, but as a Cartesian product.
Can I sum "Base Work Hours" by the column value?
On the picture above the total "Base Work Hours" should be 400.
My report:
WorkHours calculated as
select
(DATEDIFF(DAY, #dtStartDate, #dtEndDate) + 1
- DATEDIFF(WEEK, #dtStartDate, #dtEndDate) * 2
- CASE WHEN DATEPART(WEEKDAY, #dtStartDate) in (1, 7) THEN 1 ELSE 0 END
- CASE WHEN DATEPART(WEEKDAY, #dtEndDate) in (1, 7) THEN 1 ELSE 0 END
)
* WorkHoursDay
FROM tblEmpl

Related

Finding the optimal sum of a 2D array

The problem statement goes like this:
Given an N x M array of (nonnegative) integers, find the optimal value of each column in the array, taking into account free rows.
A free row is anything in the range of [prevOld, prevNew]
Free rows are given starting values of:
prevOld = 0
prevNew = 0
so at the first step, only row 0 is free. If an element lies in a free row, it incurs no penalty.
If an element is not in a free row, then the penalty incurred is 2 * distance to closest free row - (e.g if free rows are [1,3] and our element is in row 5 then the element loses 2*(5-3) value. But if the element was in row 2, then no pentalty is incurred since 1 <= 2 <= 3
Once an element has been selected, free rows are updated as such:
prevOld = prevNew
prevNew = row of selected element
So if we begin with [x,y] and choose element in row z, then for the next column, free rows are now [y,z]
We are asked to solve this using an dynamic programming algorithm.
I am having a hell of a time coming up with a recurrence relation for this problem. I originally tried an algorithm that chooses the maximum element in a column based on a "real" value given the free rows, but this doesn't take into account the fact that sometimes we want to choose a lower value in our current column for a higher value in the next column. Any point in the right direction would be greatly appreciated.
EDIT
Sample input/output (no input/output was given, so putting this together from instructions):
Input: 3 x 3 array
4 5 7
7 8 7
1 9 10
First column is 4 7 1 and our starting rows are prevOld = 0 and prevNew = 0, [0,0]
so the 0th row is the only free row, with that, the "real" values of the first column are: 4 5 -3
4 is row 0, so it is free therefore its value is not affected
7 is in row 1, which is 1 away from the closest free row 0, so it loses 2*1 value, so 7 has a "real" value of 5
1 is in row 2, which is 2 away from the closest row, so it loses 2*2 value, so 1 has a "real" value of -3
With these real values we would select 7 (row 1) as our choice. Now we update prevOld and prevNew
prevOld = prevNew
prevNew = 1 (because we selected row 1)
so now we have [0,1] as the free rows and we move onto the next column: 5 8 9
Skipping ahead: real values of this column are
5 (row 0 is free, no loss)
8 (row 1 is free, no loss)
7 (row 2 is 1 away from the closest free row, so it loses 2*1 value)
so we choose 8 (row 1) and update prevOld and prevNew again:
prevOld = prevNew
prevNew = 1 (selected row)
free rows are now [1,1] for the final column: 7 7 10
real values are: 5 7 8, so we choose 8 and were done
Output is: 1 1 2 (the rows we selected in each column), total: 21 (total of the "real" values we selected in the rows)

Easiest DAX function to add a Last 7 Day marker column to a Calendar table

I have a Calendar table and would like to add a calculated column "Is Last 7 Days" - it should be either 1 or 0 - so if DayMarker is within the last 7 days it shows 1 ortherwise 0.
I have this DAX expression which seems over-complicated - what is the easy way?
Last 7 Days =
IF(
'Calendar'[DayMarker] >=
MAXX(
ALL('Calendar')
, DATEADD('Calendar'[DayMarker],-7,DAY)
)
,1
,0
)
Try this:
Last 7 Days = IF(MAX('Calendar'[DayMarker]) - 'Calendar'[DayMarker] < 7, 1, 0)
If you prefer, you can use DATEDIFF instead of subtraction:
Last7Days = IF(DATEDIFF('Calendar'[DayMarker], MAX('Calendar'[DayMarker]), DAY) < 7, 1, 0)

Adjusting the result of query which is using round function

Suppose I have a query as:
Select round(column 1 - column 2) delta from table;
Now I want delta as delta -1 if (column 1 - column 2) results in a number with decimal value equal or more than 0.5 (like 100.65). Because the delta will be rounded to next whole number (like 101). But I want just delta (means 100 and not 101).
If (column 1 - column 2) results in a number with decimal value less than 0.5 (like 100.35) then the delta is automatically right (like 100 after rounding).
So the problem is occurring for rounding of (column 1 - column 2) when (column 1 - column 2) has a value greater than 0.5.

What does "preceding" mean in Oracle?

Could anyone please explain to me how the following code executes and what is the meaning of preceding keyword in Oracle?
SUM(WIN_30_DUR) OVER(PARTITION BY AGENT_MASTER_ID
ORDER BY ROW_DT ROWS BETWEEN 30 PRECEDING AND 1 PRECEDING)
Hey Thanks for your clarification. I have a small doubt.
Let say if we have 59 days of data from 1st jan to 28 feb. What data this function gets?
You obviously are querying a table T with columns WIN_30_DUR, AGENT_MASTER_ID and ROW_DT (among others). Keep in mind that keywords like OVER, PARTITION show you're using an analytical request: such requests allow you to get information on the current row from the other ones, that would be complex and long to write with GROUP BY or other "standard" clauses.
Here, on a given row, you:
group (PARTITION) by AGENT_MASTER_ID: this gets all the rows of T with current AGENT_MASTER_ID
in the partition formed you ORDER rows by ROW_DT
this ordering allows you to select the 30 rows before the current ROW_DT: this is the meaning of the PRECEDING keyword (0 would select the current row, the opposite is the FOLLOWING clause)
then you do a sum on the WIN_30_DUR field
In usual language, this would mean something like: for each agent, take the sum of durations of the preceding 30 days.
select row_dt, win_30_dur,
agent_master_id,
SUM(WIN_30_DUR) OVER(PARTITION BY AGENT_MASTER_ID
ORDER BY ROW_DT ROWS BETWEEN 30 PRECEDING AND 1 PRECEDING) running_sum
from test;
It uses ROWS BETWEEN 0 PRECEDING AND 0 PRECEDING for returning the results upto the current row. , that is partitioned by the column AGENT_MASTER_ID in your table which is ordered by the ROW_DT.
So, in your query it returns the sum of values of AGENT_MASTER_ID that is preceding between 30 and 1 rows above the current row.
for better understanding: see here: http://sqlfiddle.com/#!4/ce6b4/4/0
ROWS BETWEEN is the windowing clasue. It is used to specify what rows are considered while evaluating the analytic function.
Breaking down the clauses,
PARTITION BY AGENT_MASTER_ID : The rows are partitioned by agent_master_id. That means, while evaluating the function for a particular row, only those rows are considered which which have agent_master_id same as that of the current row.
ORDER BY ROW_DT : The column by which the rows are ordered within each partition.
ROWS BETWEEN 30 PRECEDING AND 1 PRECEDING : This specifies within each partition, consider only those rows starting from the row which precedes the current row by 30, till the row which precedes the current row by 1. Essentially, 30 previous rows.
For explanation purpose lets assume this is how your table looks like. Under the sum_as_analytical I have mentioned what rows are included while calculating the SUM.
agent_master_id win_30_dur row_dt sum_as_analytical
---------------------------------------------------------------------
1 12 01-01-2013 no preceding rows. Sum is null
1 10 02-01-2013 only 1 preceding row. sum = 12
1 14 03-01-2013 only 2 preceding rows. sum = 12 + 10
1 10 04-01-2013 3 preceding rows. sum = 12 + 10 + 14
. .
. .
. .
1 10 30-01-2013 29 preceding rows. sum = 12 + 10 + 14 .... until value for 29-01-2013
1 10 31-01-2013 30 preceding rows. sum = 12 + 10 + 14 .... until value for 30-01-2013
1 20 01-02-2013 30 preceding rows. sum = 10 + 14 + 10 .... until value for 31-01-2013
. .
. .
. .
1 10 28-02-2013 30 preceding rows. sum = sum of values from 29th Jan to 27th FeB
2 10 01-01-2013 no preceding rows. Sum is null
2 15 02-01-2013 only 1 preceding row. sum = 10
2 14 03-01-2013 only 2 preceding rows. sum = 10 + 15
2 12 04-01-2013 3 preceding rows. sum = 10 + 15 + 14
. .
. .
. .
2 23 31-01-2013 30 preceding rows. sum = 10 + 15 + 14 .... until value for 30-01-2013
2 12 01-02-2013 30 preceding rows. sum = 15 + 14 + 12 .... until value for 31-01-2013
. .
. .
. .
2 25 28-02-2013 30 preceding rows. sum = sum of values from 29th Jan to 27th FeB
Few other examples of windowing clasue,
UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING : All preceding rows, current row, all following rows.
2 PRECEDING and 5 FOLLOWING : 2 preceding rows, current row and 5 following rows.
5 PRECEDING and CURRENT ROW : 5 preceding rows and current row.
CURRENT ROW and 1 FOLLOWING : Current row, 1 following row.
Windowing clause is optional. If you omit it, the default in Oracle is UNBOUNDED PRECEDING AND CURRENT ROW, which essentially gives the cumulative total.
Here's a simple demo.
I found solution by assigning result into list..
List<> BOS = Orders1.ToList<>();
decimal running_total = 0;
var result_set =
from x in BOS
select new
{
DESKTOPS = x.NOTEBOOKS,
running_total = (running_total = (decimal)(running_total + x.NOTEBOOKS))
};`enter code here`

Matrix with equal sum of rows and columns

I have NxM matrix with integer elements, greater or equal than 0.
From any cell I can transfer 1 to another one (-1 to the source cell, +1 to the destination).
Using this operation, I have to make sums for all rows and columns equal. The question is how to find the minimal amount of such operations to achieve my task. During the processing cells may be negative.
For example, for
1 1 2 2
1 0 1 1
0 0 1 1
1 1 1 2
The answer is 3.
P.s.: I've tried to solve it on my own, but came only to brute-force solution.
First, find the expected sum per row and per column 1.
rowSum = totalSum / numRows
colSum = totalSum / numCols
Then, iterate through the rows and the columns and compute the following values:
rowDelta = 0
for each row r
if sum(r) > rowSum
rowDelta += sum(r) - rowSum
colDelta = 0
for each col c
if sum(c) > colSum
colDelta += sum(c) - colSum
The number of the minimum moves to equilibrate all the rows and columns is:
minMoves = max(rowDelta, colDelta)
This works because you have to transfer from rows that exceed rowSum into rows that don't exceed it, and from columns that exceed colSum into columns that don't exceed it.
If initially rowDelta was lower than colDelta, then you will attain a stage where you equilibrated all the rows, but the columns are still not equilibrated. At this case, you will continue transferring from cells to other cells in the same row. The same applies if initially colDelta was lower than rowDelta, and that's why we selected the maximum between them as the expected result.
1 If totalSum is not a multiple of numRows or numCols, then the problem has no solution.
Let us consider the one dimensional case: you have an array of numbers and you are allowed a single operation: take 1 from the value of one of the elements of the array and add it to other element. The goal is to make all elements equal with minimal operations. Here the solution is simple: you choose random "too big number" and add one to random "too small" number. Let me now describe how this relates to the problem at hand.
You can easily calculate the sum that is needed for every column and every row. This is the total sum of all elements in the matrix divided by the number of columns or rows respectively. From then on you can calculate which rows and columns need to be reduced and which - increased. see here:
1 1 2 2 -2
1 0 1 1 +1
0 0 1 1 +2
1 1 1 2 -1
+1+2-1-2
Expected sum of a row: 4
Expected sum of a column: 4
So now we generate two arrays: the array of displacements in the rows: -2,+1,+2,-1 and the number of displacements in the columns: +1,+2,-1,-2. For this two arrays we solve the simpler task described above. It is obvious that we can not solve the initial problem in fewer steps than the ones required for the simpler task (otherwise the balance in the columns or rows will not be 0).
However I will prove that the initial task can be solved in exactly as many steps as is the maximum of steps needed to solve the task for the columns and rows:
Every step in the simpler task generates two indices i and j: the index from which to subtract and the index to which to add. Lets assume in a step in the column task we have indices ci and cj and in the row task we have indices ri and rj. Then we assign a correspondence of this in the initial task: take 1 from (ci, ri) and add one to (cj, rj). At certain point we will reach a situation in which there might be still more steps in, say, the columns task and no more in the rows task. So we get ci and cj, but what do we do for ri and rj? We just choose ri=rj so that we do not screw up the row calculations.
In this solution I am making use of the fact I am allow to obtain negative numbers in the matrix.
Now lets demonstrate:
Solution for columns:
4->1;3->2;4->2
Solution for rows:
1->3;1->3;2->4
Total solution:
(4,1)->(1,3);(3,1)->(2,3);(4,2)->(2,4)
Supose thar r1 is the index of a row with maximal sum, while r2 is the row with minimal sum. c1 column with maximal sum and c2 column with minimal.
You need to repeat the following operation:
if Matrix[r1][c1] == Matrix[r2][c2] we're done!
Otherwise, Matrix[r1][c1] -= 1 and Matrix[r2][c2] += 1

Resources