Report services with multiple grouping - sql-server

I am new to reporting services. I have 2 tables:
"cars" with columns id, cartype, capacity
"values" with column id,carid, year, val1, val2
Records for these tables are:
Cars:
id cartype capacity
1 Passat 2200
2 BMW 2800
Values:
id carid year val1 val2
1 1 2012 100 1
2 1 2011 200 2
3 1 2010 300 3
4 2 2012 400 4
5 2 2011 500 5
I want to make a report that shows this:
Car Type Capacity
Passat 2200
2012 2011 2010
val1 100 200 300
val2 1 2 3
Car Type Capacity
BMV 2800
2012 2011
val1 400 500
val2 4 5
I made a data source with this select:
SELECT m.Id AS carid, m.cartype, m.capacity, v.Id AS idval, v.An, v.val1, v.val2
FROM car AS m INNER JOIN values AS v ON m.Id = v.carid
I have tried to use a matrix but I can't succeed in making this format. Can somebody help me to obtain this report?

Your Dataset is fine for this report.
You need to create a List based on the Cars Group, the within this List add two Textboxes for the Car details and a Matrix for val1, val2, etc.
A List allows you flexibility to place and move items as required, and placing a Matrix with the Cars group means it will only include values in scope for each Car. The List (and hence Car details and the values Matrix) will be repeated for each Car as required.
Added after comment:
It's impossible to say what was causing your error; it's really a specific implementation detail. To give an example of how this might be done I've mocked up a report. First step is to create the Car group:
You can see there is one Group, with one Textbox. In the Textbox there is a Rectangle (Lists in SSRS are just tables with Rectangles inserted). Car and Capacity are just Textboxes. In this example I've used two Matrices, but this could be done any number of ways. Val1:
Val2:
Final result:
So you can see it's very possible, you just need to understand the grouping required and how to construct a matrix. Unfortunately it's impossible to say what caused this error but hopefully this gives you something to aim towards.

Related

Change formula array for every X number of rows in Excel

I have large number of rows of data in Excel where I need to change the row array of the formula for every 3 rows but I can't figure out how to adjust the formula without an error.
How do I add a formula like this to the formula below?
=INT(((ROW(a1)-1)/11))*1+1
This is the formula I have been using, but I need to change it for every 3 rows.
=IF(COUNTIF($N$4:$N$6, ""), "",MAX($N$4:$N$6))
=IF(COUNTIF($N$7:$N$9, ""), "",MAX($N$7:$N$9))
And so on
Example
I have 3 approvers, if "product" is approved, the date is for the approval date of last said approval, if no approval has been made then the cell is blank. Outcome is what I want to collect from column 3 when product was approved from all 3 approvers which is the newest date of the 3 rows, if one approver has not approved, then I'd like column 4 to be blank.
Product
Approvers
Dates
Outcome
A
1
04.01.2016
04.01.2016
A
2
17.12.2015
04.01.2016
A
3
21.12.2015
04.01.2016
B
1
11.04.2017
11.04.2017
B
2
30.01.2017
11.04.2017
B
3
04.04.2017
11.04.2017
C
1
C
2
13.10.2016
C
3
14.02.2017
D
1
01.03.2022
01.03.2022
D
2
02.12.2019
01.03.2022
D
3
30.01.2020
01.03.2022
Picture of data
Two options:
To answer the original question, to make your formula change every n rows, use =-MOD(ROW()+c, n) to adjust this (where 'c' is a constant just to get them in line, if your data starts on row 2 then c would be 1).
Your formula for row 2 would be:
=IF(COUNTIF(OFFSET($N2,-MOD(ROW($N2)+1,3),0,3),""),"",MAX(OFFSET($N2,-MOD(ROW($N2)+1,3),0,3)))
Another option, not as direct an answer to the question but potentially useful if the number of products changed in future from 3 to something else, would be:
=IF(COUNTIFS(L:L, L2, N:N, ""), "", MAX(IF(L:L=L2, L:L)))
and click Ctrl+Shift+Enter after typing that in (because it's an Array formula, see here, here and here).
The advantage of this approach is that it looks at all rows where the product column is the same (I'm assuming unique products), so no need to limit it to 3 rows per product or have those 3 rows next to each other.

GDS doesn't show all rows / sum all values when I have 2 same rows of blending data

GDS doesn't show all rows / sum all values when I have 2 same rows of blending data.
I am doing a report that shows data filtered by email.
It took me 2 days but hopeless to find the root cause
Please see the screenshot for what I mean
https://i.stack.imgur.com/KJJAn.png
Here's the GDS file.
https://datastudio.google.com/s/kPkRpwDTqbc
The values which should be summed up, need to be in the metrics. Then following result is archived:
Again your raw data:
Date Sales
Rep Bill ID
Qty
Price
Total
Amount
04/08/2021
Dove
12345
1
1
1
04/08/2021
Jone
12346
1
2
2
04/08/2021
Jone
12346
1
2
2
and
Staff
Email
Dove
dove#gmail.com
Jone
dotuanviet1981#gmail.com
For joing, these values have to be in metrics, marked yellow. You put them in dimension - marked red - and therefore these counted once vor duplicated data.

BI - fact table design with incompatible grains

I'm quite new to BI designing DB, and here some point I do not understand well.
I'm trying to import french census data, where I got population for each city. For each city, I have population with different age classification, that can't really relate with each other.
For instance, let's say that one classification is 00 to 20 years old, 21 to 59, and 60+
And the other is way more precise : 00 to 02, 03 to 05, etc. but the bounds are never the same as the first one classification : I don't have 15 to 20, but 18 to 22, for example.
So those 2 classifications are incompatible. How can I use them in my fact table ? Should I use 2 fact tables and 2 cubes ? Should I use one fact table, and 2 dimensions for 1 cube ? But in this case, I will have double counted facts when I'll sum to have total population for a city, won't I ?
This is national census data, and national classifications, so changing that or estimating population to mix those classifications is not an option. And to be clear, one row doesn't relate to one person, but to one city. My facts are not individuals but cities' populations.
So this table is like :
Line 1 : One city - one amount of population - one code for dim age (ex. 00 to 19 yo) of this population - code (m/f) for the dim gender of that population - date of the census
Line 2 : Same city - one amount of population - one code for dim age (ex. 20 to 34) of this population - code (m/f) for the dim gender - date of the census
And so it goes for a lot of cities, both gender, and multiple years.
Same
I hope this question is clear enough, as english is not my native language and as I'm quite new in DB and BI !
Thanks for helping me with that.
One possible solution using a single fact table and two dimensions for the age ranges:
1 - Categorical range based on the broadest census, for example:
Young 0-20
Adult 21-59
Senior 60+
You could then link the other census to this dimension with approximate values, for example 18-22 could be Young.
2 -Original age range. This dimension could be used for precise age ranges when you report on a single city, it can also help you evaluate the impact of the overlapping bounds (e.g. how many rows are in the young / 18-22 range?)
you can crate one dimention as below
young 1-20
adult 21-59
senior 60+
Classification is
young city 1 : 1-20
young city 2 : 4-23
id field1 field2 field3 field4 .......
1 1 year young_city_1 other .......
2 2 year young_city_1 other .......
3 3 year young_city_1 other .......
4 4 year young_city_1 young_city_2 .......
Now you can report from any item and with any division
i hope it is help you

How to merge rows of SQL data on column-based logic?

I'm writing a margin report on our General Ledger and I've got the basics working, but I need to merge the rows based on specific logic and I don't know how...
My data looks like this:
value1 value2 location date category debitamount creditamount
2029 390 ACT 2012-07-29 COSTS - Widgets and Gadgets 0.000 3.385
3029 390 ACT 2012-07-24 SALES - Widgets and Gadgets 1.170 0.000
And my report needs to display the two columns together like so:
plant date category debitamount creditamount
ACT 2012-07-29 Widgets and Gadgets 1.170 3.385
The logic to join them is contained in the value1 and value 2 column. Where the last 3 digits of value 1 and all three digits of value 2 are the same, the rows should be combined. Also, the 1st digit of value 1 will always been 2 for sales and 3 for costs (not sure if that matters)
IE 2029-390 is money coming in for Widgets and Gadgets sold to customers, while 3029-390 is money being spent to buy the Widgets and Gadgets from suppliers.
How can I so this programmatically in my stored procedure? (SQL Server 2008 R2)
Edit: Would I load the 3000's into one variable table the and the 2000's into another, then join the two on value2 and right(value1, 3)? Or something like that?
Try this:
SELECT RIGHT(LTRIM(RTRIM(value1)),3) , value2, MAX(location),
MAX(date), MAX(category), SUM(debitamount), SUM(creditamount) FROM
table1 GROUP BY RIGHT(LTRIM(RTRIM(value1)),3), value2
It will sum the credit amount and debit amount. It will choose the maximum string value in the other columns, assuming they are always the same when value2 and the last 3 digits of value1 are the same it shouldn't matter.

Explaining row and column dependencies

This is a simple and common scenario at work, and I'd appreciate some input.
Say I am generating a report for the owners of a pet show, and they want to know which of their customers have bought how many of each pet. In this scenario my only tools are SQL and something that outputs my query to a spreadsheet.
As the shop owner, I might expect reports in the form:
Customer Dog Cat Rabbit
1 2 3 0
2 0 1 1
3 1 2 0
4 0 0 1
And if one day I decided to stock Goldfish then the report should now come out as.
Customer Dog Cat Rabbit Goldfish
1 2 3 0 0
2 0 1 1 0
3 1 2 0 0
4 0 0 1 0
5 0 0 0 1
But as you probably know, to have a query which works this way would involve some form of dynamic code generation and would be harder to do.
The simplest query would work along the lines of:
Cross join Customers and Pets, Outer join Sales, Group, etc.
and generate:
Customer Pet Quantity
1 Dog 2
1 Cat 3
1 Rabbit 0
1 Goldfish 0
2 Dog 0
2 Cat 1
2 Rabbit 1
...etc
a) How would I explain to the shop owners that the report they want is 'harder' to generate? I'm not trying to say it's harder to read, but it is harder to write.
b) What is the name of the concept I am trying to explain to the customer (to aid with my Googling)?
The name of the concept is 'cross-tab' and can be accomplished in several ways.
MS Access has proprietary extensions to SQL to make this happen. SQL pre-2k5 has a CASE trick and 2k5 and later has PIVOT, but I think you still need to know what the columns will be.
Some databases indeed support some way of creating cross tables, but I think most need to know
the columns in advance, so you'd have to modify the SQL (and get a database that supports such an extension).
Another alternative is to create a program that will postprocess the second "easy" table to get your clients the cross table as output. This is probably easier and more generic than having to modify SQL or dynamically generate it.
And about a way to explain the problem... you could show them in an Excel how many steps are needed to get the desired result:
Source data (your second listing).
Select values from the pets column
Place each pet type found on a new column
Count values per each type per client
Fill the values
and then say that SQL gives you only the source data, so it's of course more work.
This concept is called pivoting
SQL assumes that your data is represented in terms of relations with fixed structure.
Like, equality is a binary relation, "customer has this many pets of this type" is a ternary relation and so on.
When you see this resultset:
Customer Pet Quantity
1 Dog 2
1 Cat 3
1 Rabbit 0
1 Goldfish 0
2 Dog 0
2 Cat 1
2 Rabbit 1
, it's actually a relation defined by all possible combinations of domain values being in this relation.
Like, a customer 1 (domain customers id's) has exactly 2 (domain positive numbers) pets of genus dog (domain pets).
We don't see rows like these in the resultset:
Customer Pet Quantity
1 Dog 3
Pete Wife 0.67
, because the first row is false (customer 1 doesn't have 3 items of dog, but 2), and the second row values are out of their domain scopes.
SQL paradigma implies that your relations are defined when you issue a query and each row returned defines the relation completely.
SQL Server 2005+ can map rows into columns (that is what you want), but you should know the number of columns when designing the query (not running).
As a rule, the reports you are trying to build are built with reporting software which knows how to translate relational SQL resultsets into nice looking human readable reports.
I have always called this pivoting, but that may not be the formal name.
Whatever it's called you can do almost all of this in plain SQL.
SELECT customer, count(*), sum(CASE WHEN pet='dog' THEN 1 ELSE 0 END) as dog, sum(case WHEN pet='cat' THEN 1 ELSE 0 END) as cast FROM customers join pets
Obviously what's missing is the dynamic columns. I don't know if this is possible in straight SQL, but it's certainly possible in a stored procedure to generate the query dynamically after first querying for a list of pets. The query is built into a string then that string is used to create a prepared statement.

Resources