SQL Select Between intervals - sql

I have a list of people who have completed training sessions. I need to select all the people who have completed sessions by intervals of 5. So the list would only pull the rows when a person has reached 5, 10, 15, 20 sessions and so on.
Name Sessions
John Smith 5
Bill Smith 10
Joe Smith 15
Is there a quick way of doing this or do I have to
SELECT WHERE sessions = 5 OR 10 OR 15

Try this:
SELECT col FROM table WHERE sessions % 5 = 0

use the modulo / remainder operator from your RDBMS.
for example in postgres
SELECT *
FROM YourTable
WHERE sessions % 5 = 0

You can use the modulo operator (%) like this:
SELECT Stuff FROM Table WHERE (sessions % 5) = 0
The modulo operator calculates a remainder. When the remainder of sessions divided by 5 is zero, that means that sessions is divisible by 5.

I think you mean where the number of sessions they have done is divisible by 5.
SELECT P.PersonId, Count(S.SessionId)
FROM Person P
INNER JOIN Sesssion S ON S.PersonId = P.PersonId
GROUP BY P.PersonId
HAVING Count(S.SessionId) % 5 = 0
The HAVING is the important bit here.

Related

Ms Access database student rank for same mark

I have a table like this :
### Table name: studentresult ###
Name Cls Roll Mark result Rank
Jubayer 10 1 600 Pass
Jewel 10 2 620 Pass
James 10 3 590 Pass
Jemi 10 4 590 Pass
Kalis 10 5 449 Fail
Lelin 10 6 600 Pass
I want to generate the ranks of the students automatically. The rank will depend on the mark (higher mark implies better rank). If two students (or more) have the same mark, the roll will determine the relative ranking (lower roll implies better rank). Finally, if a student has failed, he will not be considered in the ranking.
In my example, the result would be like this :
Name Cls Roll Mark result Rank
Jubayer 10 1 600 Pass 2
Jewel 10 2 620 Pass 1
James 10 3 590 Pass 4
Jemi 10 4 590 Pass 5
Kalis 10 5 449 Fail **
Lelin 10 6 600 Pass 3
SELECT
name,
Cls,
Roll,
Mark,
CASE WHEN t.result LIKE 'Pass' THEN a.pos+1
WHEN t.result LIKE 'Fail' THEN '**'
END as Rank
FROM table t
CROSS JOIN (SELECT posexplode(split(repeat(',', 70), ','))) a
ORDER BY t.Roll
This wil create 70 rows if you have 70 students.
I have just modify the code of Mr. GordonLinoff answers. Try below query...
SELECT sr.*, IIf(sr.result="Pass",(select count(*)
from Table1 as sr2
where sr2.result = "Pass" and
(sr2.Mark*10000-sr2.roll >= sr.Mark*10000-sr.roll and sr2.roll = sr2.roll
)
),Null) AS ranking
FROM Table1 AS sr;
You can use the generic function RowRank from my project RowNumbers.
Too much code to post here, but go to paragraph 5. Rank for the details.
Example:
A bit tricky as Mark is sorted Desc while Roll is sorted Asc:
SELECT
studentresult.Name,
studentresult.Cls,
studentresult.Roll,
studentresult.Mark,
studentresult.Pass,
IIf([Pass]='Pass',RowRank("[Mark],-[Roll]","(select * from studentresult where Pass='Pass')",[Mark],-[Roll],2),Null) AS Rank
FROM
studentresult;
Output:
In MS Access, you can use a correlated subquery:
select sr.*,
iif(sr.result = "Pass",
(select count(*)
from studentresult as sr2
where sr2.result = "Pass" and
(sr2.Mark > sr.Mark or
sr2.Mark = sr.Mark and sr2.roll <= sr.roll
)
),
NULL
) as ranking
from studentresult as sr;
Note that this uses NULL for the missing value for fails. This is much more convenient than '**'. You can use the latter but you need to convert the number to a string so the entire column is a string. NULL just works.

SQL MAX() Function Not Working As Expected

I am attempting to select the max requester_req for each customer group, but after trying numerous different approaches, my result set continues to display every row instead of the max for the customer group.
The query:
SELECT
x2.customer,
x.customer_req,
x2.requester_name,
MAX(x2.requester_req) AS requester_req
FROM x, x2
WHERE x.customer = x2.customer
GROUP BY x2.customer, x2.requester_name, x.customer_req
ORDER BY x2.customer
A sample result set:
customer customer_req requester_name requester_req
Bob's Burgers 7 Bob 9
Bob's Burgers 7 Jon 12
Hello Kitty 9 Jane 3
Hello Kitty 9 Luke 7
Expected result set:
customer customer_req requester_name requester_req
Bob's Burgers 7 Jon 12
Hello Kitty 9 Luke 7
Have I screwed up something in my group by clause? I can't count how many times I've switched things up and get the same result set.
Thank you very much for your help!
select the max requester_req for each customer group
Don't aggregate. Instead, you can filter with a correlated subquery:
select
x2.customer,
x.customer_req,
x2.requester_name,
x2.requester_req
from x
inner join x2 on x.customer = x2.customer
where x2.requester_req = (
select max(x20.requester_req) from x2 x20 where x20.customer = x2.customer
)
order by x2.customer
Side note: always use explicit, standard joins (with the on keywords) instead of old-school implicit joins (with commas in the from clause): this syntax is not recommended anymore since more than 20 years, mostly because it is harder to follow.

How to calculate a progressive sum within an Access query

I have a query, let's call it qry_01, that produces a set of data similar to this:
ID N CN Sum
1 4 0 0
2 3 3 3
5 4 4 7
8 3 3 10
The values shown in this query actually come from a chain of queries and from a bunch of different tables.
The corrected value CN is calculated within the query, and counts N if the ID is not 1, and 0 if it is 1.
The Sum is the value I want to calculate by progressively summing up the CN values.
I tried to use DSUM, but I came out with nothing.
Can anyone please help me?
You could use a correlated subquery in the following way:
select t.id, t.n, t.cn, (select sum(u.cn) from qry_01 u where u.id <= t.id) as [sum]
from qry_01 t

How calc Rank with this data in my database?

i have table that store questions each question have different answers and each answer have different weight and now i want to Calculation the rank but i don't now how do this.please help me
i use sql server
i have this table stored answers and weight of each answer
AdminQuesAns
=======================
Id QuesId Ans Value
10 1000 Yes 10
11 1000 somewhat 5
12 1000 No 0
10 1001 Yes 0
12 1001 No 10
and this table store Customer answers
AdminRank
==================================
Id SDId QuesId AnsValue
1 100 1000 10
2 100 1001 0
You can use the below query.
1.
Select SDId ,b.QuesId,
((sum(a.AnsValue) *100)/(Select sum(c.value)
from AdminQuesAns c where c.QuesId =b.QuesId))as'Rank'
from AdminRank a join AdminQuesAns b on a.QuesId=b.QuesId and value=AnsValue
group by SDId ,b.QuesId
This is how I'd go about it.
This has an inner query which gets the max value for each question, then the outer query pairs those with the values from the individual answers, sums across the questions and calculates one as a percentage of the other.
I'm also grouping by SDId, on the assumption that that is the ID of the person filling out the survey.
SELECT
ar.SDId,
100 * cast(sum(ar.AnsValue) as numeric(5,2)) / sum(mv.maxValue) as Rank
FROM
AdminRank ar
JOIN
(
SELECT
qa.QuesId,
max(qa.Value) as maxValue
FROM
AdminQuesAns qa
GROUP BY
qa.QuesId
) mv on ar.QuesId = mv.QuesId
GROUP BY
ar.SDId
Depending on your data types you may be able to remove the cast part.

SQL ROUND A AVG

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.