I'm not finding any other questions exactly like mine, so it's time to ask.
I have an SSRS 2016 report. It's got a regional hierarchy (State, City, Location). And it's got one measure column that is a calculation performed in the stored procedure. Due to the nature of the calculation, the value of the calculation for a city must be performed independently in the stored procedure. It's not a simple aggregation of the Locations in the City, so it cannot simply be aggregated in the report. I need the report to expand and contract on the regional hierarchy columns, and to pull the measure values straight from the dataset with aggregating.
In other words
I have a dataset like this:
State City Location Measure
FL NULL NULL 25
FL Miami NULL 12
FL Miami Walmart 52
FL Miami Kmart 3
FL Orlando NULL 33
FL Orlando Sears 4
I need for the report to have collapsible rowgroups at the State and City levels, with Location being the "detail" level row group. But I need the value of Measure to be 12 for Miami, and not some aggregation of 2 & 3 (Walmart and Kmart).
I figure the approach must be either:
Use traditional row groups and do some kind of programming in the expression of the measure column for the two upper-level row groups, or
Don't put row groups on the tablix and do conditional formatting of the rows and some kind of programming in the toggle properties.
But in both cases, I'm not seeing anything I can do that SSRS will actually allow for the "some kind of programming" bit.
Is there a solution?
If you must do it in the report, I think you could use a table a FILTER out the NULL city and location values. When you need them you could do a Lookup to get the value from the dataset. This will lookup the Measure value for a City where the IIF will act as a filter for the NULL value - if there is a location the City will have an X0 added and won't match the Lookup City.
=Lookup(Fields!City.Value, Fields!City.Value & IIF(ISNOTHINGFields!Location.Value), "", "x0"), Fields!Measure.Value, "Dataset1")
If you can put your current results in a temp table, a better way would be to add the totals as seperate fields in the query.
SELECT 'FL' AS State, NULL AS City , NULL as Location, 25 as Measure
INTO #TABLE
UNION
SELECT 'FL' AS State, 'Miami' AS City , NULL AS Location, 12 as Measure
UNION
SELECT 'FL' AS State, 'Miami' AS City , 'Walmart' as Location, 52 as Measure
UNION
SELECT 'FL' AS State, 'Miami' AS City , 'Kmart' as Location, 3 as Measure
UNION
SELECT 'FL' AS State, 'Orlando' AS City , null as Location, 33 as Measure
UNION
SELECT 'FL' AS State, 'Orlando' AS City , 'Sears' as Location, 4 as Measure
--DROP TABLE #TABLE
SELECT T.*, T_S.Measure AS STATE_MEASURE, T_C.Measure AS CITY_MEASURE
FROM #TABLE T
LEFT JOIN #TABLE T_S ON T.State = T_S.State AND T_S.City IS NULL
LEFT JOIN #TABLE T_C ON T.State = T_C.State AND T_C.City = T.City AND T_C.Location IS NULL
WHERE T.City IS NOT NULL AND T.Location IS NOT NULL
This will let you just have the recordsd you need with the additional comlumns for the summary data.
Group on state and city and don't use SUM() for your Measure column
Your layout could be like the one below
Related
I am trying to find the average value from column B based on the distinct (country) of column A.
Argentina 49.5600
Argentina 31.5100
Austria 353.0700
Austria 67.8800
Belgium 6.2700
Belgium 0.1700
This is part of the table. I am trying to average the values in column B based on country, such as 49.5 + 31.5 averaged for only Argentina, etc.
I have tried several combinations so far with no luck.
select shipcountry, round(avg(freight), 1)
from Table.Orders
order by shipcountry;
select shipcountry,
(select round(avg(freight), 1)
from Table.Orders)
from Table.Orders
order by shipcountry;
The first query only returns one row with a single country and value. The second query returns the countries, but column B is averaged altogether. Is there a way to separate the averages by country?
No subquery needed, you're just missing the GROUP BY clause:
SELECT shipcountry, ROUND(AVG(freight),1)
FROM Table.Orders
GROUP BY shipcountry;
GROUP BY in the docs
I'm trying to create a report in SSRS where I have a matrix, which has gender as the column headings and specifically defined agegroups as the rows. The report is sorted by date (ie, the records being displayed are filtered by the modifedAt value). My problem is that i wish for all of the age group categories to be displayed, even if the dataset does not return any data for that row.
So, for example, if i set the date to be a date where there are no db rows where there are Age5-16 children in - I still want to display the category name, but just have the cells related to that row to display '0'. Instead, the report just drops the whole row because, obviously the query returns no data.
Is the solution to have a separate dataset that brings back the entire list of categories and then somehow fit them together? I'm stuck here so any help is appreciated!
I can think of a few ways to do this:
DataSet level
Instead of just returning the relevant data in the underlying data in the DataSet, include all the categories you want to display in all cases.
e.g. For a database query it might be the difference between an inner and left join, i.e. going from something like:
select *
from AgeGroup
inner join MyData on ...
to:
select *
from AgeGroup
left join MyData on ...
So the report always has all the age groups to display. Where there are NULL values, just display 0.
I think this is the best option if you have control over the DataSet - you won't have to update your report at all, with luck the actual DataSet changes should be minimal, there is still only one DataSet call, and it's by far the simplest to maintain.
Hard code groups into the report
Here you include a table header row for each group you want to display, so these are always displayed in all cases.
Here you have some sort of conditional expression to display the values, e.g. For each group row it will be tailored to that group:
=Sum(IIf(Fields!AgeGroup.Value = "5-16", Fields!Amount.Value, Nothing)
This is not too flexible and will need updates as you change groups, and doesn't have as many options for layout. There is still only one DataSet call, so that is a plus.
Subreports
You can have a parent DataSet that displays one row for each age group, then embed a subreport in each row that displays the data you want for that row.
This allows you flexibility in layout but it will add complexity to the report(s) and will mean that you make a lot of DataSet calls that could be avoided with other options.
I know this is old, but I wanted to elaborate on Ian's section 1 above using joins at the dataset level. (His answer was super helpful to me for a report I'm working on.)
per op:
Is the solution to have a separate dataset that brings back the entire list of categories and then somehow fit them together?
That is how I've handled it successfully, but you can do so without actually creating a separate dataset by using common table expressions (or temp tables, of course).
For these example tables:
AGE_Table
ID Group Group_Desc Toys
1 A 00-10 Teddy Bear
2 B 11-20 Video Game
3 C 21-30 Sports Car
4 D 31-40 Mansion
5 E 41-50 Jewelry
People_Table (filtered for whatever date)
ID Name Age Gender Age_Group
1 Ariel 07 F A
2 Brandon 23 M C
3 Chelsea 27 F C
4 Derek 06 M A
You want to see 2 results for the 00-10 row, 2 for the 21-30 row, and then still see rows for the other age groups even if there aren't any results.
We want to create a dataset with all the different age groupings and then join on it. Behold a solution using common table expressions:
with CTE_Age AS
(SELECT Distinct Age_Group from AGE_Table)
SELECT ID, Name, Age, Gender, CTE_Age.Age_Group FROM People_Table
RIGHT JOIN CTE_Age ON
People_Table.Age_Group = CTE_Age.Age_Group
This will return:
ID Name Age Gender Age_Group
1 Ariel 7 F A
4 Derek 6 M A
NULL NULL NULL NULL B
2 Brandon 23 M C
3 Chelsea 27 F C
NULL NULL NULL NULL D
NULL NULL NULL NULL E
Once you have that in your dataset, you can change NULL values to 0 on the report builder side -- I think in 2008R2 the default is just blank.
I have a query.I have table with two columns country and state.I want to display columns in following format
Country State
----------- ---------
India Delhi
Bangalore
Kolkata
Mumbai
USA California
Florida
Las Vegas
Virginia
It means "India" just appear one time in country column and and repeated values would come as blank value in country column when i select country and state from table.
Thanks in advance
Presentation is usually if not always better done outside of SQL so I'd recommend doing this in whatever your presentation layer runs, but if it's a requirement for the query, you can do it using session variables;
SELECT Country, State FROM (
SELECT IF(Country=#country, '', Country) Country, State, #country := Country
FROM (SELECT Country, State FROM Table1 ORDER BY Country, State) dummy1,
(SELECT #country:='') dummy2
) dummy3;
An SQLfiddle to test with.
Just to show a (probably) better way, you can use this to get a list of states per country, and process it further in your presentation layer;
SELECT Country, GROUP_CONCAT(State) FROM Table1 GROUP BY Country;
Another SQLfiddle.
use pl/sql.Moreover your table would be voilating 5th normal form.
i have the search requirement that with doing search option for rental house.
city,price range,numberOfRooms are the criteria.
if the user does not mention any of the details and click submit we have to show all the results.
if the user mentioned for example price range is 5000 to 10000 then it has to give the results for considering all cities,all possible 1bhk,2bhk,3bhk...
how to write single query that covers all the possibilities
i have this idea in my mind..
let us consider only city and price are the option and no other options are there for the better explanation.
i create a table called city
city
option cityname
1 delhi
2 hyderabad
3 bangalore
4 delhi
4 hyderabad
4 bangalore
SELECT *
FROM rental
WHERE city IN (select cityname from city where option=#{option_value}) and price>=#{minPrice} and price<=#{maxPrice};
Do we need to create the table city?
Is there any to send the values in list and based on option those list values should come.
is it correct?
Here is another way to do this, by using optional parameters something like:
SELECT *
FROM rental
WHERE 1 = 1
AND (#city IS NULL OR city = #city)
AND (#PricerangeFlag IS NULL OR price BETWEEN #minPrice AND #maxPrice)
..
If any of the parameters #city, #pricerangeFlag or any other parameter passed this way to this query, passed with a NULL value then the whole predicate, for example, AND (#city IS NULL OR city = #city) will be evaluated to true without getting into the second predicate OR city = #city since #city is NULL evaluates to true. The same with other parameters and if all the parameters passed with the value NULL to the query the WHERE clause wil be evaluated to WHERE 1 = 1 which is always true predicate, there for act like it wasn't presented and returns all rows.
Note that in case of the price ranges parameters I used a flag parameter to disable the two parameters #minPrice and #maxPrice
I have a table with 3 columns
Column 0: auto inc index
Column 1: Person's Gener
Column 2: The STATE the person lives in (US States and Puerto Rico)
I want to run a query that tells me how many MEN are in each state
so the output would list all 50 states (in 1 column) and the second would be a number to determine the number of MEN in that state
Alaska 1000
New York 85000
(the figures above aren't accurate but i'm illustrating what I am looking for)
Thanks
You need to use a GROUP BY clause and the COUNT aggregate function.
SELECT State, COUNT(*) AS NumberOfMen
FROM your_table
WHERE Gender = 'M'
GROUP BY State
try this
select STATE, count(*) as num from table_name where gender ='MALE' GROUP BY STATE;