I have that 2 tables:
Evaluation
id_student teste
----------- -----
1 16
1 10
1 20
1 13
Student
id name
----------- ------
1 Jonh
And I want do the average of the column "teste" for the student with the id 1.
I used that query:
select ROUND(AVG(e.teste),0) from Student s, Evaluation e
where s.id=e.id_student and s.id=1 group by s.nome
That query return the value 14, but if i go to the calculator and do (16+10+20+13) / 4 it gives me 14.75 I already tryed with the ROUND to round the number, the query should return 15 instaed of 14.
Somebody know how I can soulve this? Thanks and sorry my english.
The problem is probably that the average is calculated using integer arithmetic. You don't specify your database, but some do use integer arithmetic. This has nothing to do with the round().
Try this out:
select AVG(e.teste)
from Student s join
Evaluation e
on s.id = e.id_student
where s.id = 1;
Notice the changes:
Fixed the join use proper, explicit join syntax.
Removed the round().
Removed the group by because you only seem to want to return one row.
This will return 14 and not 15, because the calculation is integer 59 divided by integer 4 to return an integer -- so it is truncated not rounded. You can fix this by converting to some sort of decimal/float representation. Often the easiest way is just by multiplying by 1.0:
select AVG(e.teste * 1.0)
from Student s join
Evaluation e
on s.id = e.id_student
where s.id = 1;
Once you have the average calculating correctly, you can apply round() if you like.
Related
I am new to Postgres and I was wondering how to divide two columns and place that value into a new column or if that is possible with what I am currently working with. The two columns I am trying to divide into each other are already created by Count functions.
This is my current query:
select w.publisher_id, w.sub_id_2, COUNT(w.contact_id), COUNT(e.edocs_signed_date)
from leads_last_90_days w
left join enrollments e on w.contact_id = e.contact_id
where w.sub_id is not null
group by w.publisher_id, w.sub_id_2
order by publisher_id desc
And this is what my results currently look like:
publisher_id sub_id count count
"1481" "11" 148 4
"1481" "7" 8 0
"1481" "695" 209 6
"1481" "266" 5 1
"1481" "54" 95 2
How do I divide the last column into the third column to get a closing percentage in a fifth column?
You can use mathematical operators (such as /) in SQL. Note, however, that dividing two integers in PostgreSQL will result in integer division, so you'll need to cast (at least one of) them to a real using the cast operator (::):
SELECT w.publisher_id,
w.sub_id_2,
COUNT(w.contact_id),
COUNT(e.edocs_signed_date)
COUNT(w.contact_id)::real / COUNT(e.edocs_signed_date) AS percentage
FROM leads_last_90_days w
LEFT JOIN enrollments e ON w.contact_id = e.contact_id
WHERE w.sub_id IS NOT NULL
GROUP BY w.publisher_id, w.sub_id_2
ORDER BY publisher_id DESC
I am calculating a field called "Degree Level" in a view. This is a field in the table "Degrees", and the table shows degrees for each faculty member. A faculty member can have more than one degree.
The field "degree level" is also in the table "Crosswalk_Table". I want to choose Degree level for a faculty member based on the max value in the column "Degree_Hierarchy" in the Crosswalk_table.
The code below displays the "Master" instead of the "Doctor" for degree level (which has the higher hierarchy value). ANY help is much appreciated thank you.
CAST (
(SELECT DEGREE_LEVEL
FROM Degrees D, Crosswalk_Table E
WHERE
E.DEGREE_HIERARCHY =
(SELECT MAX (DEGREE_HIERARCHY)
FROM Crosswalk_Table
WHERE DEGREE_CODE = D.FACULTY_DEGREE_CODE)
AND D.FACULTY_DEGREE_CODE = E.DEGREE_CODE
AND D.PERSON_SKEY = SRC.PERSON_SKEY
AND ROWNUM <=1
ORDER BY DEGREE_HIERARCHY DESC)
AS VARCHAR2 (50))
Sample Data:
Degree table:
Person_skey Degree_Code
-------------------------
123456 MA
123456 JD
Crosswalk_Table:
degree_level degree_code degree_hierarchy
---------------------------------------------
master MA 30
doctor JD 40
If you are using Oracle 12 or higher, then you may use a subquery like that (with ORDER BY and LIMIT to 1 row):
SELECT c.DEGREE_LEVEL
FROM Degrees d
JOIN CROSSWALK_TABLE c
ON c.Degree_Code = d.Degree_Code
WHERE d.Person_skey = 123456
ORDER BY c.DEGREE_HIERARCHY DESC
FETCH FIRST ROW ONLY
Please take a look at this simple demo:
https://dbfiddle.uk/?rdbms=oracle_18&fiddle=c8d41924c593f4f361de59a611a363cc
I am using Oracle 11G.
Here is my data in table ClassGrades:
ID Name APlusCount TotalStudents PctAplus
0 All 44 95 46.31
1 Grade1A 13 24 54.16
2 Grade1B 11 25 44.00
3 Grade1C 8 23 34.78
4 Grade1D 12 23 52.17
The data (APlusCount,TotalStudents) for ID 0 is the sum of data for all classes.
I want to calculate how each class compares to other classes except itself.
Example:
Take Grade1A that has PctAplus = 54.16.
I want to add all values for Grade1B,Grade1C and Grade1D which is;
((Sum of APlusCount for Grade 1B,1C,1D)/(Sum of TotalStudents for Grade 1B,1C,1D))*100
=(31/71)*100=> 43.66%
So Grade1A (54.16%) is doing much better when compared to its peers (43.66%)
I want to calculate Peers collective percentage for each Grade.
How do I do this?
Another approach might be to leverage the All record for totals (self cross join as mentioned in the comments), i.e.,
WITH g1 AS (
SELECT apluscount, totalstudents
FROM grades
WHERE name = 'All'
)
SELECT g.name, 100*(g1.apluscount - g.apluscount)/(g1.totalstudents - g.totalstudents)
FROM grades g, g1
WHERE g.name != 'All';
However I think that #Wernfried's solution is better as it doesn't depend on the existence of an All record.
UPDATE
Alternately, one could use an aggregate along with a GROUP BY in the WITH statement:
WITH g1 AS (
SELECT SUM(apluscount) AS apluscount, SUM(totalstudents) AS totalstudents
FROM grades
WHERE name != 'All'
)
SELECT g.name, 100*(g1.apluscount - g.apluscount)/(g1.totalstudents - g.totalstudents)
FROM grades g, g1
WHERE g.name != 'All';
Hope this helps. Again, the solution using window functions is probably the best, however.
I don't know how to deal with "All" record but for the others this is an approach:
select Name,
100*(sum(APlusCount) over () - APlusCount) /
(sum(TotalStudents) over () - TotalStudents) as result
from grades
where name <> 'All';
NAME RESULT
=================================
Grade1A 43.661971830986
Grade1B 47.142857142857
Grade1C 50
Grade1D 44.444444444444
See example in SQL Fiddle
I was working on a query today which required me to use the following to find all odd number ID values
(ID % 2) <> 0
Can anyone tell me what this is doing? It worked, which is great, but I'd like to know why.
ID % 2 is checking what the remainder is if you divide ID by 2. If you divide an even number by 2 it will always have a remainder of 0. Any other number (odd) will result in a non-zero value. Which is what is checking for.
For finding the even number we should use
select num from table where ( num % 2 ) = 0
As Below Doc specify
dividend % divisor
Returns the remainder of one number divided by another.
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/modulo-transact-sql#syntax
For Example
13 % 2 return 1
Next part is <> which denotes Not equals.
Therefor what your statement mean is
Remainder of ID when it divided by 2 not equals to 0
Be careful because this is not going to work in Oracle database. Same Expression will be like below.
MOD(ID, 2) <> 0
ID % 2 reduces all integer (monetary and numeric are allowed, too) numbers to 0 and 1 effectively.
Read about the modulo operator in the manual.
In oracle,
select num from table where MOD (num, 2) = 0;
dividend % divisor
Dividend is the numeric expression to divide. Dividend must be any expression of integer data type in sql server.
Divisor is the numeric expression to divide the dividend. Divisor must be expression of integer data type except in sql server.
SELECT 15 % 2
Output
1
Dividend = 15
Divisor = 2
Let's say you wanted to query
Query a list of CITY names from STATION with even ID numbers only.
Schema structure for STATION:
ID Number
CITY varchar
STATE varchar
select CITY from STATION as st where st.id % 2 = 0
Will fetch the even set of records
In order to fetch the odd records with Id as odd number.
select CITY from STATION as st where st.id % 2 <> 0
% function reduces the value to either 0 or 1
It's taking the ID , dividing it by 2 and checking if the remainder is not zero; meaning, it's an odd ID.
<> means not equal. however, in some versions of SQL, you can write !=
Very simply, I need to find student grades using SQL.
If, for example, I have following table that define grades
Marks (int)
Grade (Char)
and the data like this:
Marks | Grade
__90 | A+
__80 | A
__70 | A-
__60 | B
__50 | C
__40 | D
Okay, having said that, if I have a student that gained marks 73, how do I calculate her grade using above gradings in SQL.
Thank you so much...
You want the highest value below or equal to your value, substitue 73 for your value...
select top 1 Grade from TableName where Mark <= 73 order by Mark desc
Assuming your GradeCutoff table is created with something like:
CREATE TABLE GradeCutoff
( mark int
, grade char(3)
)
and you want to check #studentMark
SELECT grade
FROM GradeCutoff
WHERE mark =
( SELECT max(mark)
FROM gradeCutoff
WHERE #studentMark >= mark
)
;
Note: you may also have to add a (0, 'E') row in your cutoff table.
I think you should define a UDF for this which takes student markes as parameter and returns the grade according to the table given.
Then you can get grade for any student from student table as -
select studentID, getGrade(studentMarks) from student
Here getGrade(studentMarks) is UDF and studentMarks is column in student table with marks (for eg: in your case it is 73)
HINT: You need to use CASE construct in the UDF to get the grade.
SELECT Grade FROM 'table name here' WHERE student_mark <= 79 AND student_mark >= 70 - in order to be more specific I would need to see the actual layout of the tables. But, something to that affect would work.
If the marks are actually regular multiples of 10, you could look into SQLs MOD function
Since I didn't find any way to do it using MySQL, I had to do some PHP programming to achieve the result. The goal is to get the closest value from gradings.
Okay suppose, we have the grades as defined in my question.
$MarksObt = 73 <- Marks obtained by the student:
Step 1: Get grades from mysql ordered by Marks in ASC order (ASC order is important):
SELECT marks, grade FROM gradings ORDER BY marks
Step 2: Create an array variable "$MinGrades". Loop through the result of above query. Suppose MySQL results are stored in "$Gradings" array. Now on each iteration, do the following:
Subtract the $Grading['marks'] From $MarksObt
If result is greater than or equal to 0, add the result to "$MinGrades" array
Step 3: When loop ends, the "$MinGrades" array's first element will be the closest value ... DONE
Below is the PHP code that implements the above:
$MinGrades = array();
foreach($Gradings as $Key=>$Grading){
$Subtract = $MarksObt - $Grading['marks'];
if( $Subtract >= 0 )
array_push($MinGrades, array($Key=>$Subtract))
}
$GradeKey = key($MinGrades[0]); // Get key of first element in the array
print $Gradings[$GradeKey]['grade'];
If you have some better approach, please mention here.
Thanks for your contribution...