I'd like to show an ASP.NET Chart control that shows a distribution of grades.
It should show how many students got which grade, ranging from A to F.
How do I make the chart include the grades A, B, C, D, F in the cases where no students got, say, a D letter grade? For example, I'd like the D value to to present on the X-axis, but with a student count of zero.
The data is being pulled from a database and I'm using an ObjectDataSource to bind to the chart control.
EDIT: The structure of the data is that there's a Students table and each stundent has a FirstName, LastName, and Grade.
EDIT: For the rest of the site I'm using Entity Framework with LINQ (as opposed to writing raw SQL), so, in a perfect world, the solution wouldn't involved raw SQL.
Is it possible to change your query includes all grades then fill in the details for each grade?
total hack - but to show you the idea as I don't know your schema
select * from
(
select 'a' Grade
union
select 'b' Grade
union
select 'c' Grade
union
select 'd' Grade
union
select 'f' Grade
) as grades g
outer join yourothertable t on g.Grade = t.Grade
Edit: After reading your edit realizing you don't want this to be a sql solution, then the choice is to take your objects and do a linq join on them to objects containing the grade.
see:
http://www.hookedonlinq.com/OuterJoinSample.ashx
use something like
public class Grade
{
public string LetterGrade;
}
populate a list of them, and do an outer join to your results from your query. Your new linq results collection is what you now databind.
Without know how your data is structured it's a bit difficult to give a detailed answer. Here's a way to do it using SQL Common Table Expressions (CTEs). It will organize the data so that you can easily bind it to a chart control.
This will produce a table of data as follows:
| Grade | TotalGrades |
|-------|-------------|
| A | 2 |
| B | 1 |
| C | 2 |
| D | 0 |
| E | 0 |
| F | 1 |
And here's the code:
;With Grades (Grade) as
(
SELECT 'A' Grade
UNION
SELECT 'B' Grade
UNION
SELECT 'C' Grade
UNION
SELECT 'D' Grade
UNION
SELECT 'E' Grade
UNION
SELECT 'F' Grade
),
GradeResults (Name,Grade) as
(
SELECT 'John','A'
UNION
SELECT 'Sally','B'
UNION
SELECT 'Dave','C'
UNION
SELECT 'Charlie','C'
UNION
SELECT 'Lisa','F'
UNION
SELECT 'Russ','A'
)
SELECT a.Grade, COUNT(b.Grade) as TotalGrades FROM Grades a LEFT OUTER JOIN GradeResults b on a.Grade = b.Grade
GROUP BY a.Grade
ORDER BY a.Grade;
Related
I have a Kusto DB where there are multiple tables describing entities that have shared column names, e.g. they all have an Age column. They are also prefixed with the same string so it's easy to target them all with something like union database("db").PREFIX* (granted a union isn't what I really want here). I want to return a table of the form:
TableName | max(Age)
E.g.
PrefixStudent | 12
PrefixTeacher | 65
PrefixVolunteer | 22
Is there a way to do this without hardcoding the table names?
you can use union withsource=T, for example:
union withsource=T PREFIX*
| summarize max(Age) by T
Imagine I have two tables:
Table A
Names
Sales
Department
Dave
5
Shoes
mike
6
Apparel
Dan
7
Front End
Table B
Names
SALES
Department
Dave
5
Shoes
mike
12
Apparel
Dan
7
Front End
Gregg
23
Shoes
Kim
15
Front End
I want to create a query that joins the tables by names and separates sum of sales by table. I additionally want to filter my query to remove string matches or partial matches in this case by certain names.
What I want is the following result
Table C:
A Sales Sum
B Sales Sum
18
24
I know I can do this with a query like the following:
SELECT SUM(A.sales) AS 'A Sales Sum', SUM(B.sales) AS 'B sales Sum' FROM A
JOIN B
ON B.names = A.Names
WHERE Names NOT LIKE '%Gregg%' OR NOT LIKE '%Kim%'
The problem with this is the WHERE clause doesn't seem to apply, or applies to the wrong table. Since the Names column doesn't exactly match between the two, what I think is happening is when they are joined 'ON B.names = A.Names', the extras from B are being excluded? When I flip things around though I get the same result, which is no filter being applied. The wrong result I am getting is the following:
Table D:
A Sales Sum
B Sales Sum
18
62
Clearly I have a syntax issue here since I'm pretty new to SQL. What am I missing? Thanks!
You don't need a join or a union of the tables and you shouldn't do it.
Aggregate in each table separately and return the results with 2 subqueries:
SELECT
(SELECT SUM(Sales) FROM A WHERE Names NOT LIKE '%Gregg%' AND Names NOT LIKE '%Kim%') ASalesSum,
(SELECT SUM(Sales) FROM B WHERE Names NOT LIKE '%Gregg%' AND Names NOT LIKE '%Kim%') BSalesSum
I think you want a union approach here:
SELECT
SUM(CASE WHEN src = 'A' THEN sales ELSE 0 END) AS "A Sales Sum",
SUM(CASE WHEN src = 'B' THEN sales ELSE 0 END) AS "B Sales Sum"
FROM
(
SELECT sales, 'A' AS src FROM A WHERE Names NOT IN ('Gregg', 'Kim')
UNION ALL
SELECT sales, 'B' FROM B WHERE Names NOT IN ('Gregg', 'Kim')
) t;
Here is a demo showing that the above query is working.
So im wondering if its possible for SQLite to understand number ranges.
I want to be able to have a range such as "25-30" and lookup "27" to see if it falls within that range.
The issue is that the range will contain some text beforehand such as "Alice 25-30"
An example of what Id be looking to achieve can be seen in Table3 of this link:
https://dbfiddle.uk/?rdbms=sqlite_3.27&fiddle=483f62c5fbf13998659cd5f7ebbb3ce9
More than happy for solutions that can break the string at the first number, but still keep the number so
Alice | 25-30
Not
Alice | 5-30 (ive seen this suggested before :D)
To actually create Table 3 ill be using either INNER or LEFT OUTER JOIN not just Re-creating the table but was speedier to do this
Thanks in advance.
You can do it with a join of the 2 tables like this:
INSERT INTO Table3 (`ID`, `Age`,'Age Range')
SELECT t1.ID, t1.Age, t2.`Age Range`
FROM Table1 t1 INNER JOIN Table2 t2
ON t1.Age + 0 BETWEEN `Age Range` + 0
AND SUBSTR(`Age Range`, INSTR(`Age Range`, '-') + 1) + 0
SQLite performs implicit conversions of strings to numbers when they are used in expressions with numeric operations like +0, so what the query does is to compare Age to the 1st and the 2nd part of Age Range numerically.
Note that + 0 would not be needed in ON t1.Age + 0 BETWEEN if you had defined Age as REAL which makes more sense.
Change the INNER join to LEFT join if you want the row from Table1 inserted to Table3 even if there is no matching Age Range.
See the demo.
Results:
ID
Age
Age Range
1
30
25-30
2
40.5
31-45
I have a database that is the output for a python script involving a basic game. When the code saves to the database, it saves it to a table called points with the data: name, account_name, time, score. What I want is for the data be saved into a second table when sorted by name, I will then do the same with account_name. Some of the points table:
name |account_name | time | score
oliver |Oliver | 10:29:14-01:04:2017 | 250
oliver |Oliver | 10:29:20-01:04:2017 | 500
dave |Oliver | 10:29:34-01:04:2017 | 250
What I want is for the data to be sorted into a table called name, where the score is totalled for all records with the same name and a column keeps track of how many entries have been merged(In this case, it will be equal to number of games played). For example:
name | totalpoints | totalgames
oliver| 750 | 2
dave | 250 | 1
I will use this format to do the same with account_name. I have found information on how to group and sum the data but not into a second table. Thank you in advance.
first, create your table by:
CREATE TABLE `stats` (
`name` TEXT PRIMARY KEY ON CONFLICT REPLACE,
`totalpoints` INTEGER,
`totalgames` INTEGER
);
then insert into your table with:
INSERT INTO stats
SELECT games.name, SUM(games.score) AS totalpoints, COUNT(*) AS totalgames
FROM games
GROUP BY games.name
How can I combine two select queries for the same table, which have two different where in Sqlite?
I have a table with more than 10k rows. Two example rows looks like this:
year | project | finance | flow
1990 | water | 300500 | grant
1999 | energy | 200500 | loan
My attempt does not work:
SELECT sum(finance), (select sum(finance) from table where flow = grant)
FROM table where flow = loan group by year
The result should have all results group by year and list the sum(budget) in a column for grants and a column for loans.
year | grant | loan
1990 | 62662 | 383983
1991 | 28928 | 278272
UPDATE: The first example did not correspond correctly to my use case. I had to change it.
In this case, use CASE:
SELECT year,
SUM(CASE WHEN flow = 'grant' THEN finance ELSE 0 END) AS grant_total,
SUM(CASE WHEN flow = 'loan' THEN finance ELSE 0 END) AS loan_total
FROM your_table
GROUP BY year
The logic is different than what you outlined (it's a single SELECT with a single WHERE clause) but it will effectively pivot the data you need from rows to columns.