SQL How to select data that has all values above a value - sql

Say I have a Table called "MARKS" with the columns: Value, subject_id and student_id.
Now I want to write a query to display the names of all students who have secured more than 50 in ALL subjects that they have appeared in.
How can that be achieved?
Example:
Lets say the subjects are maths, english, history.
Even if a student scores 100 in maths, 100 in english but 40 in history, he should be considered as failed and not be displayed.

There are several ways to get what you expect, but in the simplest case the HAVING clause may help. In the following query grouping is done by student_id, so the min function gets minimal value over all subjects for each student_id:
SELECT student_id
FROM marks_table
GROUP BY student_id
HAVING min(marks) > 50;
Then join student names by student_id.

I would say:
select student_id
from table
where student_id not in (
select student_id
from table
where value < 50
)
Beware, if you have nulls in student_id you'll receive incorrect results. Geta round this with a coalesce() in the sub-select

Returns all students with subjects appeared
select student_id,subject_id, value from marks
where
(case when value < 50 then 'failed' else 'pass' end ) = 'pass'

select *
from
(
select student_id, MIN(Value) as sum_value
from MARKS
group by student_id
) summed
where
sum_value > 50

Related

How can i do it in single SQL?

I have this Table like this
ID | NAME | AGE | ADDRESS | SALARY
and an ID (2)
AGE of ID 2 is 25,
Now i need to count total number of record with AGE 25. How can i do it in single SQL Query? is there any why?
i currently doing it in 2 query. in one i return AGE with ID.
select AGE from table_name where ID = 2
it return AGE 25
and 2nd query i count number of record with this AGE.
select COUNT(*) from table_name where age =25
i want to do it in one SQL Query. is there any way ?
use SQL COUNT function
select COUNT(*) from mytable where age =25
You want to count the number of rows with the same age as the specified ID?
You can use a windowed count
select Agecount
from (
select *, Count(*) over (partition by Age) Agecount
from YourTable
)t
where id=?
Use Group by with subquery
SELECT COUNT(*) AS ageCount
FROM table_name
WHERE age in (SELECT age FROM table_name WHERE ID = 2)
GROUP BY age
For Questions like this the best way is use multiple conditions using Where keyword with And-Or Operators.
This query should work for your requirement without complicating anything.
select count(*) from table_name where ID=2 and age=25;

Finding count of fields in DB with special condition

my question is:
If i have table student with student_id and other fields(not matter)
and table exam with three fields: student_id, subject_id(id from another table subject) and exam_mark.
I need to find count of students who have the same exam marks for each subject.
I have stuck on that task, you can get me idea how can i do or explain full solution.
Simple data:
For this scenario query must return count(student_id) = 4
You need nested aggregation:
select count(*)
from
(
select student_id
from tab
group by student_id
-- same min and max means only one value exists
having min(exam_mark) = max(exam_mark)
) as dt
The min/max is usually more efficient than COUNT(DISTINCT exam_mark) = 1.
If you want only students with multiple marks enhance HAVING with
AND count(*) > 1

Calculate the sum of a query that uses order by and limit Postgres

The following query returns a table of grades.
I want the sum of it and i cant figure out how to do it.
SELECT grade
FROM "GradesTable"
WHERE status='success' AND student_ID=1
ORDER BY grade DESC
LIMIT 50
I get this error:
ERROR: column "grade" must appear in the GROUP BY clause or be used
in an aggregate function
The problem here is the ORDER BY clause which you would know if you pasted the full error, instead of forcing us to recreate your problem from scratch because you didn't provide the DDL and data.
CREATE TABLE "GradesTable" ( status text, student_id int, grade int );
INSERT INTO "GradesTable" (status, student_id, grade) VALUES
('success', 1, 80),
('success', 1, 100);
Query
SELECT sum(grade) FROM "GradesTable"
WHERE status='success' AND student_ID=1
ORDER BY grade DESC
LIMIT 50
;
ERROR: column "GradesTable.grade" must appear in the GROUP BY clause or be used in an aggregate function
LINE 4: ORDER BY grade DESC
However this works,
SELECT sum(grade)
FROM "GradesTable"
WHERE status='success' AND student_ID=1
LIMIT 50
;
sum
-----
180
(1 row)
But you shouldn't have a LIMIT if you have only one agg that can only ever return one row.
SELECT sum(grade)
FROM "GradesTable"
WHERE status='success' AND student_ID=1
;
If you meant to order by sum(grade) you can do that, but you lose the ability to order by grade the second you aggregate it together. However, in this example it doesn't matter because you're only returning one row.
And as a separate note you should never quote identifiers in PostgreSQL. Make everything lowercase, never quote table names or column names.
SELECT SUM(grades)
FROM
(
SELECT grade as grades
FROM "GradesTable"
WHERE status='success' AND student_ID=1
ORDER BY grade DESC
LIMIT 50
) z

Convert table into grouped statistics of same table

In MS-SQL, I have a table hasStudied(sid, ccode, grade) (student id, course code, grade) which keeps track of the past courses a student has studied and the grade they've gotten.
As output of my query, I want to return a list of courses, with the percentage of passing (= not 'F') students in the column next to it, in descending order by that percentage, like this:
C1 : 85
C3 : 70
C2 : 67
etc.
I have currently managed to break them into two separate tables, one containing coursecode and the number of people passing the course, one containing coursecode and the number of people who have read the course.
This is done by two relatively simple statements, but requires me to do a lot of inefficient calculating in java.
Is there any way to make this in a single query?
Assuming you do not have two entries with the same student under one course, this should do it:
SELECT
ccode,
ROUND((passed::numeric(15,2) / taken_course::numeric(15,2)) * 100, 0) AS percentage_passed
FROM(
SELECT
ccode,
sum(CASE WHEN grade > 2 THEN 1 ELSE 0 END) AS passed,
count(1) AS taken_course
FROM
hasStudied
GROUP BY ccode
) foo
ORDER BY ccode
-- since you want to order DESC by values, instead do
-- ORDER BY percentage_passed
I think you are looking for the usage of cte:
create table #temp(StId int, ccode varchar(5), grade varchar(1))
insert into #temp Values (1,'A1','A'),(1,'A1','F'),(2,'A2','B'),(3,'A2','F'),(4,'A2','F'),(4,'A3','F'),(5,'A3','F')
;with cte as (
select ccode
from #temp
group by ccode
)
select cte.ccode,ratioOfPass = cast(sum(case when t.grade <> 'F' then 1.0 else 0.0 end) as float) / count(*)
from cte
inner join #temp t on t.ccode = cte.ccode
group by cte.ccode
While calculating, use sum with case-when and do not forget to cast the value of sum to float.

Getting Number of records in oracle

Am trying to fetch the number of records in the table using Count(*) along with my query condition
Sample Table is
Table: STUD_NAME
Id Name
1 Steven
2 smith
2 Ben
1 Willy
My query is
select std.name
from STUD_Name where id='2'
for this it will display the output as "Smith" and "Ben", along with i need the total number of records in the STUD_NAME table.
By right it should display the total records as "4", please help me out to solve this issue and how to form the query in this case
SELECT name,
cnt as total_count
FROM (
SELECT id
name,
count(*) over () as cnt
FROM stud_name
) t
WHERE id = 2
Assuming that id is a numeric column the single quotes around the value 2 are not needed (and are actually harmful due to the implicit data type conversion that happens in the background)
What about:
select
std.name
,(select count(1) from STUD_Name) nrofstds
from STUD_Name std where std.id='2'
select STUD_NAME.name, CNT.count
from STUD_NAME
, (select count(*) COUNT from STUD_NAME) CNT
where id='2'