How to change column name and value depending on condition? - sql

I want to change column name and value depending on condition.
My table is..
Roll Name Mark
3 Chaity 87
1 Anis 75
4 Unknown 30
2 Badol 0
And I want to get like this
Roll Name Grade
3 Chaity A+
1 Anis A
4 Unknown F
2 Badol F
Where Mark and Grade mapping is as follows:
0 to 60 is F
61 to 79 is A
80 and above is A+

A simple CASE expression will do it:
SELECT
Roll,
Name,
Grade = CASE
WHEN Mark <= 60 THEN 'F'
WHEN Mark <= 79 THEN 'A'
ELSE 'A+'
END
FROM tbl
ONLINE DEMO

you can use CASE WHEN ... or create a Grade table
SELECT Roll, Name, Grade = case when Mark >= 80 then 'A+'
when Mark between 61 and 79 then 'A'
else 'F'
end
FROM yourtable
using a Grade table
SELECT t.Roll, t.Name, g.Grade
FROM yourtable t
outer apply
(
select x.Grade
from GradeTable x
where t.Mark between x.Mark_from and x.Mark_to
) g
But isn't the grading system a bit drastic ? You either get an A or failed :(

Related

Conversion of columns to rows

ID Name M E H S
1 Sally 78 85 91 76
2 Edward 87 90 82 87
convert to
ID Name Subject Marks
1 Sally M 78
1 Sally E 85
1 Sally H 91
1 Sally S 76
2 Edward M 87
2 Edward E 90
2 Edward H 82
2 Edward S 87
The unpivot function will perform the action you're looking for, try the following:
with sample_data as (
SELECT 1 as id, 'Sally' as name, 78 as M, 85 as E, 91 as H, 76 as S UNION ALL
SELECT 2, 'Edward', 87, 90, 82, 87
)
SELECT id, name, subject, marks
from sample_data
unpivot(marks for subject in (M,E,H,S));
for more information on unpivot see the docs here:
https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#unpivot_operator
One simple approach uses a series of unions:
SELECT ID, Name, 'M' AS Subject, M AS Marks, 1 AS pos FROM yourTable UNION ALL
SELECT ID, Name, 'E', E, 2 FROM yourTable UNION ALL
SELECT ID, Name, 'H', H, 3 FROM yourTable UNION ALL
SELECT ID, Name, 'S', S, 4 FROM yourTable
ORDER BY ID, pos;
In many practical case number of columns are big enough to enlist in the query or even unknown in advance - so below approach is covering more generic cases - you don't need to know in advance number and name of columns
select id, name, key, value
from your_table t,
unnest([to_json_string((select as struct * except(id, name) from unnest([t])))]) json,
unnest(bqutil.fn.json_extract_keys(json)) key with offset
join unnest(bqutil.fn.json_extract_values(json)) value with offset
using (offset)
if applied to sample data in your question - output is

Re-Organize Access Table by converting Rows to Columns

I'm pretty new to access and SQL and need some help re-organizing a table. I have the following table (sorry for the table below - having trouble posting):
ID GroupID Distance Code Start_Finish
1 44 7 A S1
2 44 14 A F1
3 45 12 B S1
4 45 16 B F1
5 45 31 C S2
6 45 36 C F2
7 45 81 B S3
8 45 88 B F3
And need for the table to be transformed into:
GroupID Code Start_Distance Finish_Distance
44 A 7 14
45 B 12 16
45 C 31 36
45 B 81 88
try something like this
Select GroupID, Code, min(distance) as Start_distance, max(distance) as Finish_distance
from Table
group by GroupID, Code
If the min and max functions don't give you what you need, try it with First() and Last() instead.
Oops - just noticed you have 2 different entries in the output for GroupID 45 Code B - is that a requirement? With that data structure and requirement, the problem gets much more difficult.
Now I see the final column in the 1st table - I think that can be used to get the output you want:
Select GroupID, Code, mid(start_finish,2) as T, min(distance) as Start_distance, max(distance) as Finish_distance
from Table
group by GroupID, Code, T
You can use conditional aggregation for this.
select GroupID
, CODE
, max(case when Left(Start_Finish, 1) = 'S' then Distance end) as Start_Distance
, max(case when Left(Start_Finish, 1) = 'F' then Distance end) as Finish_Distance
from SomeTable
group by GroupID
, CODE

How to find number of failed grades and the number of general average?

I have A table of students and their grades.
How can I count the number of failed grades (<50)
and find the general average ( I mean the average for every student ) using sqlite?
this is the table (studentTable):
sID LessonID grade
1 1 45
1 2 50
1 3 65
2 1 44
2 2 22
2 3 91
I expect the results like this:
sID noOfFails Average
1 1 53
2 2 5
Try
SELECT
sID,
SUM(CASE WHEN grade < 50 THEN 1 ELSE 0 END) AS noOfFails,
AVG(grade) AS Average
FROM studentTable
GROUP BY sID
Demo at http://sqlfiddle.com/#!5/fcd13/1
You could use a case expression inside the count function:
SELECT sID, COUNT(CASE WHEN grade < 50 THEN 1 END) AS noOfFails, AVG(grade)
FROM mytable
You can simply run it as follows:
SELECT sID, COUNT(IIF(grade<50,1,NULL)) as noOfFails, AVG(grade) as Average
FROM studentTable GROUP BY sID

MS access 2010 SQL query Help

How can i turn a table from this form:
S_ID SUBJECT MARK
1 English 90
1 Math 40
1 Computer 30
2 English 85
2 Math 10
2 Computer 06
3 English 10
3 Math 20
3 Computer 40
To this form
S_ID English Math Computer
1 90 40 30
2 85 10 06
3 10 20 40
using SQL code,
I'm using MS Access 2010,
Thank you
SELECT S_ID ,
MAX(CASE WHEN subject = 'English' THEN mark ELSE null END) AS English,
MAX(CASE WHEN subject = 'Math' THEN mark ELSE null END) AS Math,
MAX(CASE WHEN subject = 'Computer' THEN mark ELSE null END) AS Computer
FROM myTable
GROUP BY S_ID
You want a cross-tab query which will yield a column per subject;
TRANSFORM Sum(MARK) AS TotalMark
SELECT
S_ID
FROM marks
GROUP BY S_ID
PIVOT SUBJECT;
if this is a one time exercise, you could use many statements, sequentially: something like this:
insert into new_table
select distinct s_id, 0,0,0
from old_table
then a series of updates
update new_table n
set english = (select english from old_table where s_id = n.s_id )
where s_id = n.s_id

Database Query Help required in MySQL

I am looking for help in writing a query of retrieving the values from 2 tables in MySQL.
The scenario is
Table A
ID Name Marks
===================
23 John 67
45 Mark 45
12 Ram 87
Table B has the following Structure
ID Name Evaluation Marks
==============================
45 Mark 34
78 Chris 09
98 Nancy 10
23 John 12
I am trying to write a query, where if I execute the following query
Select "SOMETHING" from Table A where Id=45
I should get Marks Column as 45+34=79, which should fetch and sum from the both the Tables A and Table B.
If I execute the query with the Id=12.
Since the Id=12, does not exists in the Table B, I should get the Marks as 87.
What would a query for the above?
I assume that the id occurs only once in your tables table a, but could be missing in both. If it always exists in table a, you can use a LEFT JOIN instead of the UNION.
SELECT COALESCE(SUM(marks), 0)
FROM
(
SELECT marks FROM a WHERE id = 45
UNION ALL
SELECT SUM(evaluation_marks) AS marks FROM b WHERE id = 45
) x
Edit
If you have all users in table a, then use
SELECT a.marks + COALESCE( SUM( b.evaluation_marks ), 0 )
FROM a
LEFT OUTER JOIN b ON ( b.id = a.id )
WHERE a.id = 45
GROUP BY a.id, a.marks
You should consider changing your table model though. Why do you store name and id twice? Can't you do it like that:
id name marks evaluation marks
=======================================
12 Ram 87 0
23 John 67 12
45 Mark 45 34
78 Chris 0 9
98 Nancy 0 10