Subtotal filtering without a group - reporting-services

I have a report with 5 groups in a Tablix. I want to have 15 total lines based on a filter of amounts within that group. A simplified version:
Group1 Cost Center Relationship Type Amount
A 100 Rel1 Small 100
A 100 Rel1 Med 100
A 100 Rel2 Small 200
Total for A Small: 300
Total for A Medium: 100
I cannot group on Type because I am ordering by Relationship.
I added 2 more group rows to make 3 (one for each Type). I used "Add total" to the existing group. I tried using an IIF(Fields!Type.value="Small",SUM(Fields!Amount.value),0) in the group row but all I get is zeroes. I am not sure if I need to specify a scope because it is in the group already.

Well, IIF(Fields!Type.value="Small",SUM(Fields!Amount.value,0) wont work as it is.
You would need:
IIF(Fields!Type.value="Small",SUM(Fields!Amount.value),0)
Or try this:
SUM(IIF(Fields!Type.value="Small",Fields!Amount.value,0))
I forget in a GROUP footer if you need to SUM() inside the logic (top example) or SUM() the result of the logic (bottom example)

Related

How to take % value for Line graph for series Groups ?/How to plot graph by sql table?

Approach 1:How to take % value for Line graph for series Groups?
I am setting up a ssrs report like with x axis(Category Group) as Finished Week, QualityPercent( as Series groups-RFT%,REwork%,Scrap%) and Values as Sum of Quantity.
In the above graph the quatities are shown in percentages based upon weeks(the actual result whose plot values are given at left side of image). Respective tables structure:
But I am getting the chart like this
Here the y axis is not plotting well asper the category values, sometimes shoots upto 250%!! or 1400% !!! (this is embarrassing).
For the above graph i used expression as:
IIF(Sum(Fields!QTY.Value,"Chart11_SeriesGroup"),Sum(Fields!QTY.Value)/Sum(Fields!QTY.Value, "DataSet_Production"),0)
What i am missing? I even used #Percent. Kindly help me.
Approach 2: How to plot the ssrs graph using below result from sql query?
FinishedWeek QualityPercent QTY Percentage
1 Rework (%) 844 0.109724
1 RFT (%) 6811 0.885465
1 Scrap (%) 37 0.004810
2 Rework (%) 742 0.094618
2 RFT (%) 7096 0.904871
2 Scrap (%) 4 0.000510
After much work done with second approach, I wrote the separate query for the above table
asper the link:
Calculating percentage within a group
select t1.FinishedWeek,t1.QualityPercent,Sum(QTY) as QTY,Sum(QTY)/ t2.TOTAL_QTY as Percentage from #temp
AS t1
JOIN (
select FinishedWeek,Sum(QTY) as TOTAL_QTY from #temp
group by FinishedWeek
) AS t2
ON t1.FinishedWeek= t2.FinishedWeek
group by t1.FinishedWeek,QualityPercent,t2.TOTAL_QTY
From above query , took the Finished Week as Category, QTY as Values, and QualityPercent as Series Groups

How to create a parent group totals based on different child group

I'm not sure if I'm phrasing this correctly...
I need help splitting a total to have multi-rows/columns inside a total;
or another way to say this is, I need to have a parent group total with based on different child group.
Please see the picture below:
I am using matrix element for my stepped report. I have 4 tiers of groups on the Y-axis, and 3 tiers of groups on X-axis. On the y-axis, I have created totals for my tier 2 - Products (Linked/non-par) and totals for my tier 3 - products (A / B).
However, for the tier 3 - products (A / B) total, I need to split that total into total-A and total-B, so that the accumulative total values (66800) would be split into the sum of product A and sum of products B.
I'd like to do this without using expressions if possible. But if there are no solution, I'm open to Expression or changing dataset w/ T-SQL (if necessary).
Any ideas?!

why top 5 with ties not giving complete record sets

My query result should give top 5 with ties records but the query mentioned below is giving 130,130,120,120,120,120,120,120,120,120
but I want the result as
130,130,120,120,120,120,120,120,120,120,110,100
select top 5 with ties b.quantity
from dbo.Products as a
inner join dbo.[Order Details] as b
on a.productid = b.productid
inner join dbo.Suppliers as c
on c.supplierid = a.supplierid
order by quantity desc
I am not able to understand why the above query is not including 110 and 100 numbers even after including Top 5 with ties.
According to MSDN about TOP WITH TIES,
WITH TIES may cause more rows to be returned than the value specified
in expression. For example, if expression is set to 5 but 2 additional
rows match the values of the ORDER BY columns in row 5, the result set
will contain 7 rows.
In your example ORDER BY quantity descgives the results as,
130
130
120
120
120
etc
You have specified TOP 5. Which means that the tied values in fifth row will be retrieved by the SELECT query. Here 5th row is 120, so all the 120 will be retrieved.
SQL Fiddle
Ordered list is cut at the 5th row. But all rows with the same "rank" come in too, otherwise it would be rather random, which of them is included and which is not.

MySQL query for items where average price is less than X?

I'm stumped with how to do the following purely in MySQL, and I've resorted to taking my result set and manipulating it in ruby afterwards, which doesn't seem ideal.
Here's the question. With a dataset of 'items' like:
id state_id price issue_date listed
1 5 450 2011 1
1 5 455 2011 1
1 5 490 2011 1
1 5 510 2012 0
1 5 525 2012 1
...
I'm trying to get something like:
SELECT * FROM items
WHERE ([some conditions], e.g. issue_date >= 2011 and listed=1)
AND state_id = 5
GROUP BY id
HAVING AVG(price) <= 500
ORDER BY price DESC
LIMIT 25
Essentially I want to grab a "group" of items whose average price fall under a certain threshold. I know that my above example "group by" and "having" are not correct since it's just going to give the AVG(price) of that one item, which doesn't really make sense. I'm just trying to illustrate my desired result.
The important thing here is I want all of the individual items in my result set, I don't just want to see one row with the average price, total, etc.
Currently I'm just doing the above query without the HAVING AVG(price) and adding up the individual items one-by-one (in ruby) until I reach the desired average. It would be really great if I could figure out how to do this in SQL. Using subqueries or something clever like joining the table onto itself are certainly acceptable solutions if they work well! Thanks!
UPDATE: In response to Tudor's answer below, here are some clarifications. There is always going to be a target quantity in addition to the target average. And we would always sort the results by price low to high, and by date.
So if we did have 10 items that were all priced at $5 and we wanted to find 5 items with an average < $6, we'd simply return the first 5 items. We wouldn't return the first one only, and we wouldn't return the first 3 grouped with the last 2. That's essentially how my code in ruby is working right now.
I would do almost an inverse of what Jasper provided... Start your query with your criteria to explicitly limit the few items that MAY qualify instead of getting all items and running a sub-select on each entry. Could pose as a larger performance hit... could be wrong, but here's my offering..
select
i2.*
from
( SELECT i.id
FROM items i
WHERE
i.issue_date > 2011
AND i.listed = 1
AND i.state_id = 5
GROUP BY
i.id
HAVING
AVG( i.price) <= 500 ) PreQualify
JOIN items i2
on PreQualify.id = i2.id
AND i2.issue_date > 2011
AND i2.listed = 1
AND i2.state_id = 5
order by
i2.price desc
limit
25
Not sure of the order by, especially if you wanted grouping by item... In addition, I would ensure an index on (state_id, Listed, id, issue_date)
CLARIFICATION per comments
I think I AM correct on it. Don't confuse "HAVING" clause with "WHERE". WHERE says DO or DONT include based on certain conditions. HAVING means after all the where clauses and grouping is done, the result set will "POTENTIALLY" accept the answer. THEN the HAVING is checked, and if IT STILL qualifies, includes in the result set, otherwise throws it out. Try the following from the INNER query alone... Do once WITHOUT the HAVING clause, then again WITH the HAVING clause...
SELECT i.id, avg( i.price )
FROM items i
WHERE i.issue_date > 2011
AND i.listed = 1
AND i.state_id = 5
GROUP BY
i.id
HAVING
AVG( i.price) <= 500
As you get more into writing queries, try the parts individually to see what you are getting vs what you are thinking... You'll find how / why certain things work. In addition, you are now talking in your updated question about getting multiple IDs and prices at apparent low and high range... yet you are also applying a limit. If you had 20 items, and each had 10 qualifying records, your limit of 25 would show all of the first item and 5 into the second... which is NOT what I think you want... you may want 25 of each qualified "id". That would wrap this query into yet another level...
What MySQL does makes perfectly sense. What you want to do does not make sense:
if you have let's say 4 items, each with price of 5 and you put HAVING AVERAGE <= 7 what you say is that the query should return ALL the permutations, like:
{1} - since item with id 1, can be a group by itself
{1,2}
{1,3}
{1,4}
{1,2,3}
{1,2,4}
...
and so on?
Your algorithm of computing the average in ruby is also not valid, if you have items with values 5, 1, 7, 10 - and seek for an average value of less than 7, element with value 10 can be returned just in a group with element of value 1. But, by your algorithm (if I understood correctly), element with value 1 is returned in the first group.
Update
What you want is something like the Knapsack problem and your approach is using some kind of Greedy Algorithm to solve it. I don't think there are straight, easy and correct ways to implement that in SQL.
After a google search, I found this article which tries to solve the knapsack problem with AI written in SQL.
By considering your item price as a weight, having the number of items and the desired average, you could compute the maximum value that can be entered in the 'knapsack' by multiplying desired_cost with number_of_items
I'm not entirely sure from your question, but I think this is a solution to your problem:
SELECT * FROM items
WHERE (some "conditions", e.g. issue_date > 2011 and listed=1)
AND state_id = 5
AND id IN (SELECT id
FROM items
GROUP BY id
HAVING AVG(price) <= 500)
ORDER BY price DESC
LIMIT 25
note: This is off the top of my head and I haven't done complex SQL in a while, so it might be wrong. I think this or something like it should work, though.

Grand totals in Telerik Reporting

I'm trying to put together what I had thought would be a fairly simple report using Telerik Reporting, and I'm having a problem.
The data source is a DataTable containing outergroupid, innergroupid, number1, and number2, sorted by outergroupid, innergroupid.
I want a report laid out like this:
Outer Group 1
Inner Group 1.1 12 14
Inner Group 1.2 11 17
Outer Group 1 Totals: 23 31
Outer Group 2
Inner Group 2.1 22 24
Inner Group 2.2 21 37
Outer Group 2 Totals: 43 61
Totals: 66 92
And all of this is pretty easy, except the final grand total.
I created a group on outergroupid, and added a header with the id, and a footer with id, "Totals:", and Sum() on the numeric fields, and that handled the subtotals fine.
My problem: if I add a grand totals line in the report footer, I get a page break between the detail and the report footer - which I can't have. I've fiddled with KeepTogether, and it doesn't seem to have made a difference.
My next try was to create a global group within the detail. I'd figured that if I introduced a group with no grouping expression, it's GroupFooter would process after everything. It didn't.
So, what I need is either a way to keep the report footer from breaking onto another page, or a way to create a group that groups on everything.
Any ideas?
Solution 1 (on a 'traditional' report): add a fake group on top the real group. With a condition e.g. like "1=1".
Note: do not use the footer for this.
Solution 2: use a table item (a.k.a crosstab). On a table item, you can easily have totals and grandtotals.
The table item (with its details, totals and grandtotals) will be on the same report's section. E.g. on the report's Detail section.
You must create a report to have 2 grouping ,first you already have , A second is group that upper level than your current group,and then that group you must set data for grouping(fake data column from Databse ) at whole report , at last on report set show group footer then set content you want to.
For easy designing you can use a table object or it applies to normal report too.
Add a row group on the detail section and then add a parent row group of the 1st group by allowing the wizard (if comes any) to add their header and footer rows.
Now after all rows (in detail section) add a new row (for grand total). Any aggregated value added in this new row shall a grand total and will be shown on the same page.