Group By multiple fields,but order in the sequential manner - reporting-services

I have a design question for my SSRS report. I need to design a table in my report which is grouped by multiple field but sort in sequential manner. The table is supposed to be grouped by school name, number, and department, but the table needs to be sort in certificate number. As you can see my table grouped in the right way, but doesnt display by the certificate number.
I created by table with adding parent groups for School name, number, and department, but I am sorting the table in certificate number.
My table:
Design table:

easy peasy.
In the groupings pane at the bottom right click on school_name group and got to properties/edit group
then on the left hand side there is sorting option, select it
and choose certificate column from the drop down menu.
Upvote means it worked.

Related

Database Design for a system that has Facebook like groups

I'm creating a system that has Groups. These can be thought of like Facebook Groups. Users can create new groups. Currently I have the following types of groups:
City Group - Groups based on a certain city. For example "London Buy and Sell Group"
School Group - Groups based on schools. For example "London University Study Group"
Interest Group - Groups that are not tied to a place. For example "Over 50's Knitting Group"
In the future more group types will be added. Each group can have different types of options, but all groups have the same basic data:
An ID
A creator ID
A name
An option description
I'm struggling on putting together a database design for this. My initial thought was to create different tables for the different groups.
For example have a single table called group. This table has an id, creator id, name, description, member count, timestamps.
Then have other tables to represent the other groups, and link them to group. So I have a city_group table that contains and id, group_id, city_id. And the same for the other group types.
The only problem I have with this is interest_group doesn't have any extra data that a normal group. But for the purpose of being able to query only Interest Groups I thought it might make sense to create an interest_group table. It would only have the following columns: id, group_id, timestamps ... which seems a bit wasteful to have a table just for this purpose.
Here's a diagram to make things easier:
Are there any issues with my solution, or any better ways to solve this design problem?
I've got an idea, which is a workaround basically: have another table like: group_type in which you have id(the PK) and then you have tablename (the full table name of the type).
Then, you should have a FK from your Group table linking to this group_type table.
id tablename
--------------------
1 School Group
2 Interest Group
After all this is done, you could build your queries based on the values from this table, as an example:
JOIN (SELECT tablename FROM group_type WHERE id=group.group_type_id) ON ..

SSRS report - add extra table and chart to show occurence of character string in one of the main report's columns

I have an SSRS report based on stored procedure dataset. The report shows employees and their performance rating and uses bunch of parameters to filter the data.
Now I would like to add a table below that would dynamicaly count and show occurence of given mark in the main report. The table data should update according to what is visible in the main report after filtering it.
I wanted also to add a chart that would visualize this.
It would be feasible to do if the extra table and chart could run from the same dataset as the main report. This however seems impossible as this dataset does not always contain all the possible marks. It can happen that some marks are missing (when filtered or missing at all), and I would like to show the mark with zero value (and zero value bar in the chart) instead of just skipping it.
So far I was able to produce the table by hardcoding the headers and using SUM(IIF...) expressions under each header
Here is the expression for the "C" column.
=Sum(IIf(Fields!current_performance_rating.Value = "C", 1, 0))
It shows correctly the number of "C" marks appearing in the main report.
Now I am stuck with creating a chart that would show this.
I am not able to hardcode expressions similar to the ones in the table
and can't make the chart run from the main dataset, because the categories
would be missing after filtering the report (and not showing zero).
I tried linking datasets with Lookup function, but that did not work.
Which way should I go now? What is the best practice in such case?
Thank you for any hints!
Thanks trubs.
I have right joined a view that contains
all the marks and that solves the issue
of missing categories.
The join is on something like
tb.current_performance_rating = vw.performance_rating_code
I can now add the value series that counts
the occurence of current_performance_rating
per category. This works all fine.
However there is another table joined
(on employee_id) that stores last year's rating.
This rating obviously may differ to the current one.
On the same chart I would like to add another
series that counts last year's rating per category.
The category is there already, joined to the current
rating.
So you can have row like:
curren rating | last year's rating | category
C | H | C
So I am stuck, because when SSRS groups per category
it counts last year's H rating and displays
i the C category, while it should display it in H.
Sorry I can't post any pictures, seems like I
need more reputation points.
Hope you can understand what I mean.
Regards!
You're likely better off changing your query to return results for marks where there are no values.
So instead of inner joining to your Performance Rating table, use a Right Join or Full Outer Join, so that all the data is always available.
eg: Instead of...
SELECT p.PersonId, PersonName, g.Grade
FROM Person p
INNER JOIN PersonGrades pg ON p.PersonId = pg.PersonId
INNER JOIN Grades g ON pg.GradeId = pg.GradeId
Use
SELECT p.PersonId, PersonName, g.Grade
FROM Grades g
LEFT JOIN PersonGrades pg ON pg.GradeId = g.GradeId
LEFT JOIN Person p ON p.PersonId = pg.PersonId
If that's not clear, post your query and we could help get the data in the right format.
The way to go was to simplify the dataset that the main report was based on.
Then I took the query from that dataset, used COUNT and GROUB BY to count number of occurence of each current year mark in the main report. Then I right joined (thx trubs!) with the view that contains all the possible marks (so that my extra table headers/chart categories would not disappear if they do not exist). As a result I got the number of occurence in current year per mark (table A).
Then I did almost exactly the same for the last year's rating, just used last year's mark. I got the number of occurence of last year's mark per mark (table B).
I inner joined table A and B on common column (the mark, which will always appear thanks to the RIGHT joins). This gave me a table (dataset eventualy) where I had:
mark | current year mark count | last year mark count.
Making a table and chart basing on this was really easy then.
There was some more fun of adding all the parameters from the main report to both the count queries, so that the counts would change when report is filtered. I also needed to make sure that count works not only when my filter criteria (in WHERE stetement) equal the parameter provided from the report, but also when they are NULLs (so I added OR column_i_filter_on IS NULL).
This works smoothly - the table content and chart changes when filtering changes (although runs slowly, as parameters are passed to two big dataset, one of which uses them twice).
Thanks for all the help!!
psh

Pulling different records from multiple tables as one transaction history list

I am working on an employee management/reward system and need to be able to show a single "transaction history" page that shows in chronological order the different events that the employee has experienced in one list. (Sort of like how in facebook you can goto your history/action section and see a chronological list of all the stuff that you have done and affects you, even though they are unrelated to eachother and just have you as a common user)
I have different tables for the different events, each table has an employee_id key and an "occured" timestamp, some table examples:
bonuses
customers
raise
complaints
feedback
So whenever an event occurs (ie a new customer is assigned to the employee, or the employee gets a complaint or raise) a new row is added to the appropriate table with the employee ID it affects and a timestamp of when it occured.
I need a single query to pull all records (upto 50 for example) that include the employee and return a history view of that employee. The field names are different in each table (ie the bonus includes an amount with a note, the customer includes customer info etc).
I need the output to be a summary view using column names such as:
event_type = (new customer, bonus, feedback etc)
date
title (a brief worded title of the type of event, specified in sql based on the table its referencing)
description (verbiage about the action, such as if its event_type bonus display the bonus amount here, if its a complain show the first 50 characters of the complaint message or the ID of the user that filed the complaint from the complaints table. All done in SQL using if statements and building the value of this field output based on which table it comes from. Such as if its from the customers table IF current_table=customers description='A customer was assigned to you by'.customers.assigner_id).
Ideally,
Is there any way to do this?
Another option I have considered, is I could do 5-6 different queries pulling the records each from their own table, then use a mysql command to "mesh/interleave" the results from all the queries into one list by chronological order. That would be acceptable too
You could use a UNION query to merge all the information together and use the ORDER BY clause to order the actions chronologically. Each query must have the same number of fields. Your ORDER BY clause should be last.
The examples below assume you have a field called customer_name in the customers table and bonus_amount in the bonuses table.
It would look something like this:
SELECT 'New Customer' as event_type, date,
'New customer was assigned' as title,
CONCAT('New Customer: ', customer_name, ' was assigned') as description
FROM customers
WHERE employee_id = 1
UNION
SELECT 'Bonus' as event_type, date,
'Received a bonue' as title,
CONCAT('Received a bonus of $', FORMAT(bonus_amount, 2), '.') as description
FROM bonuses
WHERE employee_id = 1
UNION
...
ORDER BY date DESC;

What is the best way to count rows in a mySQL complex table

I have a table with the following fields (for example);
id, reference, customerId.
Now, I often want to log an enquiry for a customer.. BUT, in some cases, I need to filter the enquiry based on the customers country... which is in the customer table..
id, Name, Country..for example
At the moment, my application shows 15 enquiries per page and I am SELECTing all enquiries, and for each one, checking the country field in customerTable based on the customerId to filter the country. I would also count the number of enquiries this way to find out the total number of enquiries and be able to display the page (Page 1 of 4).
As the database is growing, I am starting to notice a bit of lag, and I think my methodology is a bit flawed!
My first guess at how this should be done, is I can add the country to the enquiryTable. Problem solved, but does anyone else have a suggestion as to how this might be done? Because I don't like the idea of having to update each enquiry every time the country of a contact is changed.
Thanks in advance!
It looks to me like this data should be spread over 3 tables
customers
enquiries
countries
Then by using joins you can bring out the customer and country data and filter by either. Something like.....
SELECT
enquiries.enquiryid,
enquiries.enquiredetails,
customers.customerid,
customers.reference,
customers.countryid,
countries.name AS countryname
FROM
enquiries
INNER JOIN customers ON enquiries.customerid = customers.customerid
INNER JOIN countries ON customers.countryid = countries.countryid
WHERE countries.name='United Kingdom'
You should definitely be only touching the database once to do this.
Depending on how you are accessing your data you may be able to get a row count without issuing a second COUNT(*) query. You havent mentioned what programming language or data access strategy you have so difficult to be more helpful with the count. If you have no easy way of determining row count from within the data access layer of your code then you could use a stored procedure with an output parameter to give you the row count without making two round trips to the database. It all depends on your architecture, data access strategy and how close you are to your database.

How do I keep one column consistently updated?

I have a faculty table, and each faculty has a certain number of students under him/her. So there is a 'current' column, which is the number of students currently under them.
However, I don't want to ++ and -- every time I switch a student to another faculty. Is there a way to keep the column updated with a query that uses count()? I find it is easier and more accurate to use the query 'select count() from student where advisor = 2' for example that using my current column.
To do this, use a view:
CREATE VIEW studentCount AS
SELECT
profID,
profName,
whatever,
(SELECT COUNT(*)
FROM studentTable
WHERE studentTable.profID=profTable.profID
) AS studentCount
FROM profTable;
Obviously, this needs to be massaged a little to fit your schema, but essentially, setup your view to have all the columns of the table with the faculty info and add a column at the end that counts the number you want in it.
Triggers could be a solution to you problem?
http://dev.mysql.com/doc/refman/5.5/en/triggers.html
You could create a trigger that automaticly updates your faculty table every time a student switch faculty.