total row count of parent group (summarize total) - ssrs-2012

I have a table which has 2 groups and the second group is nested from first like so
Parent - Child - Col
X X1 xx
xx
X2 xx
xx
xx
---------------------
Y Y1 yy
yy
I only care about getting the count of Cols For each parent group
like This is the desired result
Parent - Child - Col
X X1 xx
xx
X2 xx
xx
xx
Total : 5
----------------------
Y Y1 yy
yy
Total : 2
I actually managed to get total of Child group using expression =Count(Fields!Col.Value) by putting cell inside any of the 2 groups and I tried to sum it by clicking on it and choose total but it do it for all table not the parent group

I assume it's the 2 that you can't get?
If so then you can get this by counting the number of distinct Parents
=CountDistinct(Fields!Parent.Value, "myDataSetName")
"myDataSetName" is the name of the dataset you are counting from, it is case sensitive and must be enclosed in quotes.

Related

How to prove greedy is correct to uva 10026

The original program description is:
A shoemaker has N orders from customers which he must satisfy. The shoemaker can work on only one job in each day, and jobs usually take several days. For the ith job, the integer Ti ( 1$ \le$Ti$ \le$1, 000) denotes the number of days it takes the shoemaker to finish the job.
But popularity has its price. For each day of delay before starting to work on the ith job, the shoemaker has agreed to pay a fine of Si ( 1$ \le$Si$ \le$10, 000) cents per day. Help the shoemaker by writing a program to find the sequence of jobs with minimum total fine.
Input
The input begins with a single positive integer on a line by itself indicating the number of the test cases, followed by a blank line. There is also a blank line between two consecutive cases.
The first line of each case contains an integer reporting the number of jobs N, where 1$ \le$N$ \le$1, 000. The ith subsequent line contains the completion time Ti and daily penalty Si for the ith job.
Output
For each test case, your program should print the sequence of jobs with minimal fine. Each job should be represented by its position in the input. All integers should be placed on only one output line and each pair separated by one space. If multiple solutions are possible, print the first one in lexicographic order.
The output of two consecutive cases must be separated by a blank line.
Sample Input
1
4
3 4
1 1000
2 2
5 5
Sample Output
2 1 3 4
On Internet, I see the best solution is greedy on job's ratio of time and fine. But I don't think it is as simple as self-explanatory, so how to prove it strictly? Thanks!
Thanks, #mrmcgrep. I got the answer as this:
Let's say we have job 1, 2, ..., n, and they have time and fine as t1, f1, t2, f2, ..., tn, fn
and they are in the order of t1/f1 <= t2/f2 <= t3/f3 <= ... <= tn/fn
So this is the objective schedule. Now we change 1 with m (1 < m <= n)
By the original order, we need pay fine as much as:
F1 = t1 * (f2 + ... + fn) + t2 * (f3 + ... + fn) + ... + tm * (fm+1 + ... + fn) + R
By the new order, we need pay fine as much as:
F2 = tm * (f1 + ... + fm-1 + fm+1 + ... + fn) + t1 * (f2 + ... + fm-1 + fm+1 + ... + fn) + ... + fm-1 * fm+1 + ... + fn) + R
F1 - F2 = (t1 + t2 + ... + tm-1) * fm - (tm * f1 + tm * f2 + ... + tm * fm-1)
As t1 * fm <= tm * f1, t2 * fm <= tm * f2, ..., tm-1 * fm <= tm * fm-1
F1 - F2 <= 0
So the original order is the best order.

How to match a value from a table upto a particular position in oracle?

I have to write a query to match values in two tables, Table A and Table B , Table A is havingvalues in column XYZ as "91517181","915171812", i want to check if its exist in table B or not , but in table B, the value in column ABC is "9151718", but in another column in table B it is having its match length as "10". Which means it is upto "9151718XXX".
So i have to write a query where value from table A should match with value in table B, because in table B, the value is upto 10 characters.
Kindly help...
I think that you need something like this:
table a: table b:
xyz x y
---------- ---------- ---
9151718 9151718 10
91517181 91360 5
913601
select a.xyz, rpad(xyz, b.y, 'x') result, b.x pattern, b.y len
from a
left join b on a.xyz like b.x||'%' and length(a.xyz)<=b.y
xyz result pattern len
---------- ---------- ---------- ---
9151718 9151718xxx 9151718 10
91517181 91517181xx 9151718 10
913601 <- not matched
I think something like that:
select * from a where
exists(select 'x' from b where substr(xyz, 1, y) = x)
x - value in b
y - length in b

Query in Oracle for running sum

I need to pull the result set with sum of the previous record and current record.
Logic
My table is having one key column C1 and a numeric column C2. I need a result like below example. I need 3 columns as the out put out which 1 columns is with running sum. First two columns are same as source with the thrid columns but
The first record of C3 = first record C2.
Second record C3 = "First Record C2 + Second Record C2";
Third record C3 = "First Record C2 + Second Record C2 + Thrid Record C2"
and it should continue for all the records.
Ex.
I have one source table like
C1 C2
---------
a 1
b 2
c 3
I Need output like below
C1 C2 C3
-------------
a 1 1
b 2 3
c 3 6
select c1, c2, sum(c2) over (order by c2) c3
from table_name

Is there an algorithm that can divide a number into three parts and have their totals match the original number?

For example if you take the following example into consideration.
100.00 - Original Number
33.33 - 1st divided by 3
33.33 - 2nd divided by 3
33.33 - 3rd divided by 3
99.99 - Is the sum of the 3 division outcomes
But i want it to match the original 100.00
One way that i saw it could be done was by taking the original number minus the first two divisions and the result would be my third number. Now if i take those 3 numbers i get my original number.
100.00 - Original Number
33.33 - 1st divided by 3
33.33 - 2nd divided by 3
33.34 - 3rd number
100.00 - Which gives me my original number correctly. (33.33+33.33+33.34 = 100.00)
Is there a formula for this either in Oracle PL/SQL or a function or something that could be implemented?
Thanks in advance!
This version takes precision as a parameter as well:
with q as (select 100 as val, 3 as parts, 2 as prec from dual)
select rownum as no
,case when rownum = parts
then val - round(val / parts, prec) * (parts - 1)
else round(val / parts, prec)
end v
from q
connect by level <= parts
no v
=== =====
1 33.33
2 33.33
3 33.34
For example, if you want to split the value among the number of days in the current month, you can do this:
with q as (select 100 as val
,extract(day from last_day(sysdate)) as parts
,2 as prec from dual)
select rownum as no
,case when rownum = parts
then val - round(val / parts, prec) * (parts - 1)
else round(val / parts, prec)
end v
from q
connect by level <= parts;
1 3.33
2 3.33
3 3.33
4 3.33
...
27 3.33
28 3.33
29 3.33
30 3.43
To apportion the value amongst each month, weighted by the number of days in each month, you could do this instead (change the level <= 3 to change the number of months it is calculated for):
with q as (
select add_months(date '2013-07-01', rownum-1) the_month
,extract(day from last_day(add_months(date '2013-07-01', rownum-1)))
as days_in_month
,100 as val
,2 as prec
from dual
connect by level <= 3)
,q2 as (
select the_month, val, prec
,round(val * days_in_month
/ sum(days_in_month) over (), prec)
as apportioned
,row_number() over (order by the_month desc)
as reverse_rn
from q)
select the_month
,case when reverse_rn = 1
then val - sum(apportioned) over (order by the_month
rows between unbounded preceding and 1 preceding)
else apportioned
end as portion
from q2;
01/JUL/13 33.7
01/AUG/13 33.7
01/SEP/13 32.6
Use rational numbers. You could store the numbers as fractions rather than simple values. That's the only way to assure that the quantity is truly split in 3, and that it adds up to the original number. Sure you can do something hacky with rounding and remainders, as long as you don't care that the portions are not exactly split in 3.
The "algorithm" is simply that
100/3 + 100/3 + 100/3 == 300/3 == 100
Store both the numerator and the denominator in separate fields, then add the numerators. You can always convert to floating point when you display the values.
The Oracle docs even have a nice example of how to implement it:
CREATE TYPE rational_type AS OBJECT
( numerator INTEGER,
denominator INTEGER,
MAP MEMBER FUNCTION rat_to_real RETURN REAL,
MEMBER PROCEDURE normalize,
MEMBER FUNCTION plus (x rational_type)
RETURN rational_type);
Here is a parameterized SQL version
SELECT COUNT (*), grp
FROM (WITH input AS (SELECT 100 p_number, 3 p_buckets FROM DUAL),
data
AS ( SELECT LEVEL id, (p_number / p_buckets) group_size
FROM input
CONNECT BY LEVEL <= p_number)
SELECT id, CEIL (ROW_NUMBER () OVER (ORDER BY id) / group_size) grp
FROM data)
GROUP BY grp
output:
COUNT(*) GRP
33 1
33 2
34 3
If you edit the input parameters (p_number and p_buckets) the SQL essentially distributes p_number as evenly as possible among the # of buckets requested (p_buckets).
I've solved this problem yesterday by subtracting 2 of 3 parts from the starting number, e.g. 100 - 33.33 - 33.33 = 33.34 and the result of summing it up is still 100.

Interpolation between two values in a single query

I want to calculate a value by interpolating the value between two nearest neighbours.
I have a subquery that returns the values of the neighbours and their relative distance, in the form of two columns with two elements.
Let's say:
(select ... as value, ... as distance
from [get some neighbours by distance] limit 2) as sub
How can I calculate the value of the point by linear interpolation? Is it possible to do that in a single query?
Example: My point has the neighbour A with value 10 at distance 1, and the neighbour B with value 20 at distance 4. The function should return a value 10 * 4 + 20 * 1 / 5 = 12 for my point.
I tried the obvious approach
select sum(value * (sum(distance)-distance)) / sum(distance)
which will fail because you cannot work with group clauses inside group clauses. Using another subquery returning the sum is not possible either, because then I cannot forward the individual values at the same time.
This is an ugly hack (based on a abused CTE ;). The crux of it is that
value1 * distance2 + value2 * distance1
Can, by dividing by distance1*distance2, be rewritten to
value1/distance1 + value2/distance2
So, the products (or divisions) can stay inside their rows. After the summation, multiplying by (distance1*distance2) rescales the result to the desired output. Generalisation to more than two neighbors is left as an exercise to the reader.YMMV
DROP TABLE tmp.points;
CREATE TABLE tmp.points
( pname VARCHAR NOT NULL PRIMARY KEY
, distance INTEGER NOT NULL
, value INTEGER
);
INSERT INTO tmp.points(pname, distance, value) VALUES
( 'A' , 1, 10 )
, ( 'B' , 4, 20 )
, ( 'C' , 10 , 1)
, ( 'D' , 11 , 2)
;
WITH RECURSIVE twin AS (
select 1::INTEGER AS zrank
, p0.pname AS zname
, p0.distance AS dist
, p0.value AS val
, p0.distance* p0.value AS prod
, p0.value::float / p0.distance AS frac
FROM tmp.points p0
WHERE NOT EXISTS ( SELECT * FROM tmp.points px
WHERE px.distance < p0.distance)
UNION
select 1+twin.zrank AS zrank
, p1.pname AS zname
, p1.distance AS dist
, p1.value AS val
, p1.distance* p1.value AS prod
, p1.value::float / p1.distance AS frac
FROM tmp.points p1, twin
WHERE p1.distance > twin.dist
AND NOT EXISTS ( SELECT * FROM tmp.points px
WHERE px.distance > twin.dist
AND px.distance < p1.distance
)
)
-- SELECT * from twin ;
SELECT min(zname) AS name1, max(zname) AS name2
, MIN(dist) * max(dist) *SUM(frac) / SUM(dist) AS score
FROM twin
WHERE zrank <=2
;
The result:
CREATE TABLE
INSERT 0 4
name1 | name2 | score
-------+-------+-------
A | B | 12
Update: this one is a bit cleaner ... ties are still not handled (need a window function or a LIMIT 1 clause in the outer query for that)
WITH RECURSIVE twin AS (
select 1::INTEGER AS zrank
, p0.pname AS name1
, p0.pname AS name2
, p0.distance AS dist
FROM tmp.points p0
WHERE NOT EXISTS ( SELECT * FROM tmp.points px
WHERE px.distance < p0.distance)
UNION
select 1+twin.zrank AS zrank
, twin.name1 AS name1
, p1.pname AS name2
, p1.distance AS dist
FROM tmp.points p1, twin
WHERE p1.distance > twin.dist
AND NOT EXISTS ( SELECT * FROM tmp.points px
WHERE px.distance > twin.dist
AND px.distance < p1.distance
)
)
SELECT twin.name1, twin.name2
, (p1.distance * p2.value + p2.distance * p1.value) / (p1.distance+p2.distance) AS score
FROM twin
JOIN tmp.points p1 ON (p1.pname = twin.name1)
JOIN tmp.points p2 ON (p2.pname = twin.name2)
WHERE twin.zrank =2
;
If you actually want the point in between, there is a built-in way of doing that (but not an aggregate function):
SELECT center(box(x.mypoint,y.mypoint))
FROM ([get some neighbours by distance] order by value limit 1) x
,([get some neighbours by distance] order by value offset 1 limit 1) y;
If you want the mean distance:
SELECT avg(x.distance)
FROM ([get some neighbours by distance] order by value limit 2) as x
See geometrical function and aggregate functions in the manual.
Edit:
For the added example, the query could look like this:
SELECT (x.value * 4 + y.value) / 5 AS result
FROM ([get some neighbours by distance] order by value limit 1) x
,([get some neighbours by distance] order by value offset 1 limit 1) y;
I added missing () to get the result you expect!
Or, my last stab at it:
SELECT y.x, y.x[1], (y.x[1] * 4 + y.x[2]) / 5 AS result
FROM (
SELECT ARRAY(
SELECT value FROM tbl WHERE [some condition] ORDER BY value LIMIT 2
) x
) y
It would be so much easier, if you provided the full query and the table definitions.

Resources