SSRS Single row for Grouping - reporting-services

I'm working with SharePoint Lists, I have 2 Lists for this issue i.e. Movies & Theatres. Only one list is used tough, because Theatres reference a movie.
(I know this is weird but I'm not actually working with movies and theatres, it's just using an analogy so anyone could understand the problem so let's assume each Theatre only plays a single movie :-P )
So from the Theatres list I create a dataset with following fields: Linked_Movie (Title), Country, Theatre_Number.
I want to create a report that shows a tablix that lists all Movie-titles with all the countries it's shown in and a count of the theatres that are playing that movie. So the tablix should look like example below:
MovieTitle | Country | # of theatres
| |
Movie 1 | Country A | 5
| Country B | 10
SubTotal | 2 | 15
| |
Movie 2 | Country C | 15
SubTotal | 1 | 15
| |
Total | 3 | 30
I have already created a tablix which groups on Linked_Movie first and Country second. Then in the details-section I just count the theatres that play that certain movie in that specific country. To achieve this I created a second dataset with the exact same data so I could use LookUpSet.Length. But even though my calculations are correct the tablix still generates a row for each individual theatre. So my tablix actually looks like example below:
MovieTitle | Country | # of theatres
| |
Movie 1 | Country A | 5
| | 5
| | 5
| | 5
| | 5
.... | ... | ...
So if anyone knows how I would be able to achieve a tablix like the first example that would be greatly appreciated.
If anything is still unclear please don't hesitate to ask.
Kind regards
Gravinco

I was able to solve it by adding a calculated field to the dataset named MovieCountry.
After this I put the expression below as the condition for 'Row visibility' and the visiblity of the '=(Details)' properties:
=iif(Fields!MovieCountry.Value = Previous(Fields!MovieCountry.Value), True, False)
This way I only get a single row for each movie and country combination.
Any questions are always welcome!

Related

VB.NET selecting multiple columns of MySql table simultaneously into lists

I have a MySQL table that looks like this (attached below).
I want to simultaneously select (in a single SQL Query) multiple columns (id, Last Name, and username) and import into them into different lists of strings the values if they meet a certain condition (in this case, where color="blue".
+----+------------+-----------+----------+----------------+
| id | First Name | Last Name | Username | Favorite Color |
+----+------------+-----------+----------+----------------+
| 1 | John | Smith | jsmith | Blue |
| 2 | Avery | Nelson | aNelson | Red |
| 3 | Jack | Brooklyn | jBrook | Blue |
| 4 | Arnold | Nam | aNam | Blue |
| 5 | Charlie | Smith | cSmith | Orange |
+----+------------+-----------+----------+----------------+
... Continued
I am trying to select all the required data that meet the condition where color=Blue with the MySQL query of SELECT id, Last Name, username FROM `myTable` WHERE color="Blue". Once this data is selected, I want to import each selected column that meets the color requirement into separate lists.
For example, list FirstName should be list of strings "John, Jack, Arnold" (in that order) and Username list should contain "jsmith, jBrook, aNam" etc. In the end, I want to be able to produce three lists that contain these values which meet the Favorite Color condition in the MySQL database of Blue. How can I do this?
I know that I can make three separate reader queries but I want to do them all in one to save time.
You have not posted VB code so I'm not sure how you intend to use the results but you could load the whole table to a Datatable (unless it is really big), then use Dataview.RowFilter to filter your data with different criteria in-memory, without making any further request to the database backend.
You can see an example in VB.net here
Then you could use LINQ for example to generate a list of string from a datatable or view, see here for an example.

SQL ORDER BY using a value in another table using an equation grouped by duplicates

I have been given a movie database and I am trying to order by user rating held in a separate table to my movie information.
My problem is that my database does NOT have an overall rating of a movie, but only singular user ratings attached to that movie. But I want to order it by the overall average rating
For example:
SELECT Movies.title, Movies.movie_id, Movies.poster, Ratings.rating
FROM Movies INNER JOIN Ratings
ON Movies.movie_id = Ratings.movie_id
WHERE genre LIKE '%action%' AND (origin = 'american')
ORDER BY Ratings.rating DESC;
*(Rating is only selected to showcase to you the values, I do not need to use them outside this query)
This works out to display
+-------------------------+----------+------------------------------------+--------+
| title | movie_id | poster | rating |
+-------------------------+----------+------------------------------------+--------+
| The Baytown Outlaws | 2 | posters/The Baytown Outlaws.jpg | 5 |
| A Dark Truth | 8 | posters/A Dark Truth.jpg | 4 |
| A Dark Truth | 8 | posters/A Dark Truth.jpg | 3 |
| American Made | 14 | posters/American Made.jpg | 3 |
| Avengers: Age of Ultron | 4 | posters/Avengers Age of Ultron.jpg | 3 |
| Romeo Must Die | 1 | posters/Romeo Must Die.jpg | 3 |
| Avengers: Age of Ultron | 4 | posters/Avengers Age of Ultron.jpg | 2 |
| Fast & Furious 6 | 3 | posters/Fast & Furious 6.jpg | 2 |
| Olympus Has Fallen | 9 | posters/Olympus Has Fallen.jpg | 1 |
+-------------------------+----------+------------------------------------+--------+
Now from this I want to have my query select groups based on movie title, add up the ratings of that group, average that value, and then order titles by that average and excluding duplicate title names from the return
So my ideal query would return:
+-------------------------+----------+------------------------------------+
| title | movie_id | poster |
+-------------------------+----------+------------------------------------+
| The Baytown Outlaws | 2 | posters/The Baytown Outlaws.jpg |
| A Dark Truth | 8 | posters/A Dark Truth.jpg |
| American Made | 14 | posters/American Made.jpg |
| Romeo Must Die | 1 | posters/Romeo Must Die.jpg |
| Avengers: Age of Ultron | 4 | posters/Avengers Age of Ultron.jpg |
| Fast & Furious 6 | 3 | posters/Fast & Furious 6.jpg |
| Olympus Has Fallen | 9 | posters/Olympus Has Fallen.jpg |
+-------------------------+----------+------------------------------------+
So this returns my movie info ordered by average rating then excluding duplicate titles
Baytown Outlaws has 1 rating at 5 -> overall 5
Dark Truth has 2 ratings at 4 and 3 -> overall rating of 3.5 but only displays one row of movie info
American Made has 1 rating at 3 -> overall 3
etc.
I am having a lot of trouble figuring out this exact query, or if it is even possible. Any help or keyword suggestion would be useful as I am somewhat new to SQL and don't know all of its strengths. If not possible, I would also appreciate an answer saying so, so that I can go ahead and rework the database system to instead follow a better system of saving the overall rating within the Movies table.
A combination of COUNT(*) and SUM(rating) group by movie_id (or title).
Something like this:
SELECT Movies.title, Movies.movie_id, Movies.poster, SUM(Ratings.rating)/COUNT(*) AS avg_rating
FROM Movies INNER JOIN Ratings
ON Movies.movie_id = Ratings.movie_id
WHERE genre LIKE '%action%' AND (origin = 'american')
GROUP BY Movies.movie_id ORDER BY avg_rating DESC;
It can be done with the AVG function and a group by on multiple columns.
The tricky part of using AVG in that case is that when using such a function, every element in the SELECT part must either be in the GROUP or be an aggregate function. That being said, If you make groups by a combination of ID and Movie title, you would obtain the same result (in this case) as if you grouped by ID only.
You can use that to your advantage to add these columns in your SELECT section while using the AVG aggregate function.
In your first table, every time you look at the A Dark Truth movie, it comes with the same id, 8. Every time you look at the value Avengers: Age of Ultron, it comes with the same id, 4.
I suggest taking a few minutes and drawing a Venn diagram of the problem to get a good grasp of it as it seems this is material of a class.
I made a fiddle to demonstrate it for you. You can play around with it and add your initial join and where to complete it, I did a slight variation of the initial model, the create table is also in the fiddle.
SELECT Movie_id, Title, Poster, AVG(Rating)
FROM MoviesRatings
GROUP BY Movie_id, Title, Poster
ORDER BY AVG(Rating) DESC

SSRS Multiple page for each DataSet's row

Ciao, this is my scenario.
I'm building a Report with SQL Server Reporting Services.
I have two DataSet:
Continent
Countries
And I build a report like that:
+----+-----------+
| ID | Continent |
+----+-----------+
| 01 | Europa |
+----+-----------+
+----+-------------+
| ID | Countries |
+----+-------------+
| 01 | Italia |
+----+-------------+
| 02 | Switzerland |
+----+-------------+
| 03 | Germany |
+----+-------------+
| 04 | Etc. |
+----+-------------+
My report work good for one page. Now I would generate multiple pages like that:
Page 1
+----+-----------+
| ID | Continent |
+----+-----------+
| 01 | Europa |
+----+-----------+
+----+-------------+
| ID | Countries |
+----+-------------+
| 01 | Italia |
+----+-------------+
| 02 | Switzerland |
+----+-------------+
| 03 | Germany |
+----+-------------+
Page 2
+----+-----------+
| ID | Continent |
+----+-----------+
| 01 | America |
+----+-----------+
+----+-------------+
| ID | Countries |
+----+-------------+
| 01 | USA |
+----+-------------+
| 02 | Equador |
+----+-------------+
| 03 | PerĂ¹ |
+----+-------------+
| 04 | Etc. |
+----+-------------+
How can I generate multiple pages like example above?
Thanks
It looks like combining the two datasets into one and then grouping on continent would work. You can then set a page break after each continent to produce the output you're looking for.
In the group properties select the option to break "Between each instance of a group."
Join the datasets together in TSQL
Select ContinentId = c.ContinentId ,
Continent = c.Name,
CountryId = country.CountryId,
CountryName = Country.Name
From Contintent c
Inner Join Country on Country.ContinentId = c.ContinentId
Add a table (or tablix) to your design surface. Assign the above data set to your table.
Right click on the details group, Add Group | Parent Group
Group by ContinentId
Click OK
Now go to group properties (of parent group) and Set the page break
Will produce the following output.
I had the need for a report that was 4 pages long per each row in Dataset (read: 66 rows, 66 4-page reports). No rows needed to be displayed, just lots of textboxes with values all over the place on all 4 pages from the dataset row.
I added a Tablix control, and deleted the header row and all the columns in the details row. Then I added a Rectangle to that row. Then I right clicked on the left side of the Details row and added a Parent Group Row that grouped on my row's unique ID (in this case, Client ID). Then I went into Group Properties and checked Page Breaks "Between Each Instance of a Group". This was thanks to info in #Trubs answer above.
I made the first rectangle the size of a page more or less (10in, .5in margins) and clicked on the left border and picked "Insert Row, Inside Group Below". Boom. That was my next page. However, just touching that row causes a TextBox to pop into and take the row's shape so you can write something. All fine and dandy, but I had a bunch of textboxes I needed to set up. So, very carefully, I made sure the TextBox was highlighted and right clicked > Deleted it. And then very carefully I went over to tool box and added a Rectangle. Set the Rectangle to page size more or less, and added my various textboxes.
I repeated this for 2 more pages. Always double checking by previewing to make sure they printed out 2 sided (which is a printer setting.)
I looked at each Rectangle property that I used to outline each page and the option "Keep contents together on same page if possible" was checked, which is probably why everything didn't go "sprong" and add extra blank pages. Not sure, but I wasn't too precise about any page breaks anywhere else but what I have outlined above.
I hope this helps someone. Sometimes you don't need a detail section with a bunch of rows of data. This was my solution to generate a 4-page report with each row's data all over the 4-pages. The Tablix was bound to the Dataset.

MySQL query to compare content of one column with title of other column

I know the title makes no sense at first glance. But here's the situation: the DB table is named 'teams'. In it, there are a bunch of columns for positions in a soccer team (gk1, def1, def2, ... , st2). Each column is type VARCHAR and contains a player's name. There is also a column named 'captain'. The content of that column (not the most fortunate solution) is not the name of the captain, but rather the position.
So if the content of 'st1' is Zlatan Ibrahimovic and he's the captain, then the content of 'captain' is the string 'st1', and not the string 'Zlatan Ibrahimovic'.
Now, I need to write a query which gets a row form the 'teams' table, but only if the captain is Zlatan Ibrahimovic. Note that at this point I don't know if he plays st1, st2 or some other position. So I need to use just the name in the query, to check if the position he plays on is set as captain. Logically, it would look like:
if(Zlatan is captain)
get row content
In MySQL, the if condition would actually be the 'where' clause. But is there a way to write it?
$query="select * from teams where ???";
The "Teams" table structure is:
-----------------------------------------------------------------
| gk1 | def1 | def2 | ... | st2 | captain |
-----------------------------------------------------------------
| player1 | player2 | player3 | ... | playerN | captainPosition |
-----------------------------------------------------------------
Whith all fields being of VARCHAR type.
Because the content of the captain column is the position and not the name, and you want to choose based on the position, this is trivial.
$query="select * from teams where captain='st1'";
Revised following question edit:
Your database design doesn't allow this to be done very efficiently. You are looking at a query like
SELECT * FROM teams WHERE
(gk1='Zlatan' AND captain='gk1') OR
(de1='Zlatan' AND captain='de1') OR
...
The design mandates this sort of query for many functions: how you can find the team which a particular player plays for without searching every position? [Actually you could do that by finding the name in a concatenation of all the positions, but it's still not very efficient or flexible]
A better solution would be to normalise your data so you had a single table showing which player was playing where:
Situation
Team | Player | Posn | Capt
-----+--------+------+------
1 | 12 | 1 | 0
1 | 11 | 2 | 1
1 | 13 | 10 | 0
...with other tables which allow you to identify the Team, Player and Postion referenced here. There would need to be some referential checks to ensure that each team had only one captain, and only plays one goalkeeper, etc.
You could then easily see that the captain of Team 1 is Player 11 who plays in position 2; or find the team (if any) for which player 11 is captain.
SELECT Name FROM Teams
WHERE Situation.Team = Teams.id
AND Situation.Capt = 1
AND Situation.Player = Players.id
AND Players.Name = 'Zlatan';
A refinement on that idea might be
Situation
Team | Player | Posn | Capt | Playing
-----+--------+------+------+--------
1 | 12 | 1 | 0 | 1
1 | 11 | 2 | 1 | 1
1 | 13 | 10 | 0 | 0
1 | 78 | 1 | 0 | 0
...so that you could have two players who are goalkeepers (for example) but only field of them.
Redesigning the database may be a lot of work; but it's nowhere near as complicated or troublesome as using your existing design. And you will find that the performance is better if you don't need to use inefficient queries.
By what have you exposed, you just need to put the two conditions and check if the query returned 1 record. If it returns no records, he is not the captain:
SELECT *
FROM Teams
WHERE name = 'Zlatan Ibrahimovic' AND position = 'st1';

Chart reporting in SSRS

I am using SQL Server Reporting to display data using a chart. How do I create my dataset so that the graph displays one line for males & one line for females.
Thanks
Beth
Do you mean two lines as in
one per x or y axis
one per data series
This stupid thing won't allow me to comment so I'm wasting space with an answer
I think what you want is to separate the males and females into different data series. You can go this in the chart properties, as long as you have enough information in your data set.
If your data set looks something like this:
+-----------+-----+-------+
| Date | Sex | Count |
+-----------+-----+-------+
| 2009-01-1 | M | 124 |
+-----------+-----+-------+
| 2009-01-1 | F | 78 |
+-----------+-----+-------+
| 2009-01-2 | M | 95 |
+-----------+-----+-------+
| 2009-01-2 | F | 101 |
+-----------+-----+-------+
Then if you have the Date as the X-Axis variable, Count as the Y-Axis, and add the Sex as the Series Grouping, the it should automatically split them into two graph lines, and add a Legend etc.