Calculate sum of one row and divide by sum of another row. Oracle view/query - sql

This is my first question on here so bear with me. I have two tables in my Oracle database as following:
modules with fields:
module_code eg. INF211
module_title eg. Information technology
credits eg.20
module_progress with fields:
student_id eg. STU1
module_code eg. INF211
module_year eg. 1
module_percent eg. 65
Each student takes 5 modules a year.
So this is what I want to put this all in one query/view if possible:
Find sum of module percents for a particular student
Find sum of all credits for each module with regards to their module percents.
Divide sum of module percents by sum of credits and multiply by 100 to give me an average grade.
Can this be done?

SELECT student_id,
SUM(credits * module_percent) / SUM(credits) * 100.0
FROM module_progress mp
JOIN modules m
ON m.module_code = mp.module_code
GROUP BY
student_id

Related

Join multiple tables in Microsoft SQL Server where there is only one line match from table 1 and multiple lines from table 2 and 3

I am stuck on something, which I have never used in my 10 years of SQL. I thought it would be useful if there was someway of doing this. Firstly I am running SQL Server Express (latest free version) on Windows. To talk to the database I am using SSMS.
There are three tables/queries.
1 table (A) has one data value I want to pull through.
2 tables (B)/(C) have multiple values.
Column common to all tables is CAMPAIGN NAME
Column common to (B)/(C) is PRODUCT NAME
This is an example of the data:
OUTPUT GOAL
I have tried the following:
UNION ALL (but this does not assist when I want to calculate AMOUNT - MARKETING - TOTAL INVESTMENT
I tried PARTITION (but I simple could now get it to work.
If I use joins, it brings through a head count / total investment and marketing cost per product, which when using SUM brings through the incorrect values for head count / total investment and marketing cost vs total amount, quantity.
I tried splitting the costs based on Quantity / Total Quantity or Amount / Total Amount, but the cost associated with the product is not correct or directly relating to the product this way.
Am I trying to do something impossible, or is there a way to do this in SQL?
The following comes pretty close to what you want:
select . . . -- select the columns you want here
from a join
b
on b.campaign_name = a.campaign_name join
c
on c.campaign_name = b.campaign_name and
c.product_name = b.product_name;
This produces a result set with a separate row for each campaign/product.

Possible to keep fraction in a query?

I am looking for a way to add up averages in SQL. Here is an example of the data I have:
product avg_price
phone 104.28
car 1000.00
And I'm looking to build something like this:
product avg_price
[all] 544.27
phone 104.28
car 1000.00
The way I'm currently doing it is to store the count and sum in two different columns, such as:
product cnt total
phone 203 20,304.32
car 404 304,323.30
And from that get the average. However, I was wondering if it is possible in SQL to just 'keep the fraction' and be able to add them as needed. For example:
product avg_price
[all] [add the fractions]
phone 20,304.32 / 203
car 304,323.30 / 404
Or do I need to use two columns in order to get an average of multiple aggregated rows?
You don't need 2 columns to get the average, but if you want to display as a fraction then you will need both numbers. They don't need to be in 2 columns though.
select product, sum(total) ||'/'||sum(count)
from table a
join table b on a.product=b.product
union
select product, total ||'/'||count
from table a
join table b on a.product=b.product;

TOTAL vs Aggr in QlikView

I'm trying to understand how TOTAL and Aggr work in QlikView. Could someone please explain the difference between the two examples below, and if possible please illustrate with a SQL query?
Example1:
Max({<Field1=>} Aggr(Sum({<Field2={'Value'}, Field1=>} StuffCount), Field1))
Example2:
Max({<Field1=>} TOTAL Aggr(Sum({<Field2={'Value'}, Field1=>} StuffCount), Field1))
Not sure what you mean with and SQL query in this example. Anyway, imagine you have this list of Customers (CustomerID) and Sales (Sales):
CustomerID/ Sales
Customer1 25
Customer2 20
Customer1 10
Customer1 5
Customer1 20
Customer3 30
Customer2 30
Then you want to show it on a pivot table with dimension CustomerID and two expressions:
Max(Aggr(Sum(Sales), CustomerID)) // this will show 60 for the first customer, 50 for the second and 30 for the third one
Max(TOTAL Aggr(Sum(Sales),CustomerID)) //this will show 60 in every row of your table (which is the maximum sum of sales among all customers)
So basically AGGR creates a temporal list of whatever you put in the first function input (in this case sum(Sales)) using the dimension of the second (CustomerID). Then you can perform operations on that list (such as Max, Min, Avg...). If you write TOTAL and use the expression in a pivot table, then you 'ignore' the dimensions that might be affecting the operations.
Hope it helps
TOTAL keyword is useful in charts/pivot tables. It applies the same calculation on every datapoint in the chart/pivot, with independence of dimentions.
Therefore - if you put your expression into pivot table - 1st option may display different values per cell (if the Aggr is rellevant) when the 2nd will result in same values.
Aggr function allows making double aggregations (avg of sum, max of count etc..) on different group by bases.

Average function on different columns in HIVE

I want to find the average of 3 columns using hive query.
Consider the below data:
I need to find the average marks scored by each student and then the average of total marks in each school:
NULL should be ignored.
My output should look like this:
Can you guys help me out here
Hive should automatically ignore NULL values on aggregates as reported here.
For readability, I suggest using COALESCE instead of IF IS NULL statements such as: COALESCE(Math,0) as Math
Average of each student:
select school,SL_No,Name,Math,Phy,Chem,(if(Math is NULL,0,Math)+if(Phy is NULL,0,Phy)+if(Chem is NULL,0,Chem))/3 as avg_marks from my_table
Average Marks of each school
select school,avg(avg_marks) from (select school,SL_No,Name,Math,Phy,Chem,(if(Math is NULL,0,Math)+if(Phy is NULL,0,Phy)+if(Chem is NULL,0,Chem))/3 as avg_marks from my_table
) temp group by school

Very special join on float value

I got stuck with a tricky query (in MS Access 2013). I'd like to do a fairly simple Thing:
I have got two Tables (see example below): Table "scores" with scores of an exam and table "grading_key".
The scores table has a field named "quotient" which contains a float value representing the percentage of success (1.0 being all questions answered correctly). The grading_key table has quotient limits which separate one grade level from the next. Thus the “grading_key” table can be used to get a grade for any quotient value.
A grade can be found by performing:
SELECT TOP 1 Grade FROM grading_key WHERE {ANY_QUOTIENT_VALUE} <= Quotient
Sample Tables:
|-grade_key-| |-----scores-----|
Quotient Grade StudentId Quotient
0,92 1 123 0,85
0,87 1,5 321 0,8
0,81 2 766 0,91
0,76 2,5 222 0,78
My Problem is, I’d like to join scores and grades in a query resulting in associating each quotient in table “scores” with one grade in table “grade_key” (see desired_result below). Unfortunately I can’t simply join, as the quotients in “scores” do not necessarily match the grade limits defined in “grade_key”.
Currently I used a VBA function (calculateScoreForQuotient()) but I want to remove the VBA dependency as the resulting table should be called from outside MS Access and in this case VBA functions do not work.
|--------Desired_Result-------|
StudentId Quotient Grade
123 0,85 2
312 0,8 2,5
Does anyone know a way to get desired table with plain SQL? I played around with different combinations of JOINs and and WHEREs for quite a while now but my best result was to associate all available grades with each student (not really meaningful).
Any help would safe my day ;-)
You can use a co-related sub-query to return the grade based on the quotient of the student. You could use Max() or TOP 1 with an order by clause, whichever you prefer.
select
StudentID,
Quotient,
(select Max(grade) from Grades where grades.quotient <= student.quotient) as grade
from Student