Ms Access database student rank for same mark - sql

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.

Related

Oracle SQL Count function

I am hoping someone can advise on the below please?
I have some code (below), it is pulling the data I need with no issues. I have been trying (in vain) to add a COUNT function in here somewhere. The output I am looking for would be a count of how many orders are assigned to each agent. I tried a few diffent things based on other questions but can't seem to get it correct. I think I am placing the COUNT 'Agent' statement and the GROUP BY in the wrong place. Please can someone advise? (I am using Oracle SQL Developer).
select
n.ordernum as "Order",
h.employee as "Name"
from ordermgmt n, orderheader h
where h.ordernum = n.ordernum
and h.employee_group IN ('ORDER.MGMT')
and h.employee is NOT NULL
and n.percentcomplete = '0'
and h.order_status !='CLOSED'
Output I am looking for would be, for example:
Name Orders Assigned
Bob 3
Peter 6
John 2
Thank you in advance
Name
Total
49
49
49
49
49
John
4
John
4
John
4
John
4
Peter
2
Peter
2
Bob
3
Bob
3
Bob
3
for example. so there are 49 blank rows summed up as 49 in the Total column. I did not add the full 49 blank columns to save space
Would be easier with sample data and expected output, but maybe you are looking for something like this
select
n.ordernum as "Order",
h.employee as "Name",
count(*) over (partition by h.employee) as OrdersAssigned
from ordermgmt n, orderheader h
where h.ordernum = n.ordernum
and h.employee_group IN ('ORDER.MGMT')
and h.employee is NOT NULL
and n.percentcomplete = '0'
and h.order_status !='CLOSED'
The use of COUNT (as other aggregate functions) is simple.
If you want to add an aggregate function, please group all scalar fields in the GROUP BY clause.
So, in the SELECT you can manage field1, field2, count(1) and so on but you must add in group by (after where conditions) field1, field2
Try this:
select
h.employee as "Name",
count(1) as "total"
from ordermgmt n, orderheader h
where h.ordernum = n.ordernum
and h.employee_group IN ('ORDER.MGMT')
and h.employee is NOT NULL
and n.percentcomplete = '0'
and h.order_status !='CLOSED'
GROUP BY h.employee

Can I populate the 'in' variable using a list of values stored in one field

I hope I'm not trying to do something that is not possible. ..
In my DB, the query below works and gets the values I want.
select LabelID, Amount
from tCASpreadsData
where LabelID in (3,4,5,7,9,10,11,12,16,17,18,19,21,22,23,24,28,29,30)
However, I don't want to build the list of LabelIDs manually each time. I also don't have a way to logically select them. So, I created a table with all the values listed in one field.
The query below finds the list I want in a field called SumA.
select SumA from tlCECLRatio where CATemplateID = 1 and LabelID = 148
(3,4,5,7,9,10,11,12,16,17,18,19,21,22,23,24,28,29,30)
However, when I combine the two queries, I get nothing.
SELECT LabelID, Amount
FROM tCASpreadsData
WHERE convert(nvarchar(255),LabelID) in
(Select SumA from tlCECLRatio where CATemplateID = 1 and LabelID = 148)
How can I use the value of SumA to create the 'in' list in my where clause?
you can try like below no need conversion
SELECT LabelID, Amount FROM tCASpreadsData where LabelID in
(
Select SumA from tlCECLRatio where CATemplateID = 1 and LabelID = 148
)
This will work:
select LabelID, Amount
from tCASpreadsData
where LabelID in (
select SumA
from tlCECLRatio
where CATemplateID = 1 and LabelID = 148
)
From your OP, it seems like you have the freedom to define the interim table (tlCECLRatio) however you like. So, I would like to suggest that you define it without a varchar field and instead use all integer fields. Here's how it would look with the values you have provided:
CATemplateID LabelID
1 3
1 4
1 5
1 7
1 9
1 10
1 11
1 12
1 16
1 17
1 18
1 19
1 21
1 22
1 23
1 24
1 28
1 29
1 30
If you need other collections of labels, you would give them a new template ID. Each collection is therefore defined by the value of CATemplateID.
To query the values you want, it's a simple join.
select SD.LabelID, SD.Amount
from tCASpreadsData SD inner join tlCECLRatio CR
on SD.LabelID = CR.LabelID
where CR.CATemplateID = 1
Side Note: I have been taught that the interim table also needs its own row ID, so I would probably define it as CECLRatioValue(RatioValueID, CATemplateID, LabelID) where RatioValueID is a sequence (or autonumber) value. But, that might be overkill for a simple cross-reference table. Just pointing out what has been recommended to me as good database practice.

Count Instances Of Occuring String With Unique IDs

I need to count the number of times that a specific string occurs but they when one ID has the same string more than once, only count it once. Basically, I need to count the number of occurrences of a string that occur uniquely to an ID. I believe this should be a simple thing to do but I don't know what I'm doing. Here is my current code:
SELECT
RXNAME as Name,
DUPERSID as ID,
COUNT(RXNAME) as Number
FROM
`OmniHealth.PrescriptionsMEPS`
GROUP BY
ID,
Name
ORDER BY
Number
When run, it says everything was counted as 1. Thanks for the help!
UPDATE:
Dataset: https://storage.googleapis.com/omnihealth/MepsPrescriptionData.csv
OUTPUT when run with code above:
Row Name ID Number
1 SUMATRIPTAN 68896102 1
2 IBUPROFEN 65063102 1
3 PENICILLN VK 66179101 1
4 FUROSEMIDE 63217102 1
5 HYSINGLA ER 70373101 1
6 FUROSEMIDE 76090101 1
7 SKELETAL MUSCLE RELAXANTS 78414101 1
8 AMOXICILLIN 69467103 1
9 TRAMADOL HCL 67667101 1
10 PANTOPRAZOLE 60737102 1
11 CARBAMIDE PEROXIDE 6.5% OTIC SOLN 63990104 1
12 PROMETH/COD 68433101 1
13 AZITHROMYCIN 79045102 1
14 METRONIDAZOL 75414101 1
15 DEXILANT 69625101 1
16 TRAMADOL HCL 66890203 1
17 AZITHROMYCIN 73838101 1
18 COLCRYS 63856102 1
19 PERMETHRIN 62103107 1
20 ACETAMINOPHEN TAB 500 MG 62456102 1
not sure if it is what you asked - but if you are looking for DISTINCT COUNT - go with below:
#standardSQL
SELECT
RXNAME AS Name,
COUNT(DISTINCT DUPERSID) AS Number
FROM `OmniHealth.PrescriptionsMEPS`
GROUP BY 1
ORDER BY Number DESC
Try this...You are grouping on a different field than you are counting. I think you are meaning to group by RXNAME.
SELECT
RXNAME as Name,
DUPERSID as ID,
COUNT(RXNAME) as Number
FROM
`OmniHealth.PrescriptionsMEPS`
GROUP BY
ID,
RXNAME
ORDER BY
Number
I think you want:
SELECT DUPERSID as ID, COUNT(DISTINCT RXNAME) as Number
FROM `OmniHealth.PrescriptionsMEPS`
GROUP BY ID
ORDER BY Number;
This assumes that "same string" means "same value for RXNAME".

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.

Select row with shortest string in one column if there are duplicates in another column?

Let's say I have a database with rows like this
ID PNR NAME
1 35 Television
2 35 Television, flat screen
3 35 Television, CRT
4 87 Hat
5 99 Cup
6 99 Cup, small
I want to select each individual type of item (television, hat, cup) - but for the ones that have multiple entries in PNR I only want to select the one with the shortest NAME. So the result set would be
ID PNR NAME
1 35 Television
4 87 Hat
5 99 Cup
How would I construct such a query using SQLite? Is it even possible, or do I need to do this filtering in the application code?
Since SQLite 3.7.11, you can use MIN() or MAX() to select a row in a group:
SELECT ID,
PNR,
Name,
min(length(Name))
FROM MyTable
GROUP BY PNR;
You can use MIN(length(name))-aggregate function to find out the minimum length of several names; the slightly tricky thing is to get corresponding ID and NAME into the result. The following query should work:
select mt1.ID, mt1.PNR, mt1.Name
from MyTable mt1 inner join (
select pnr, min(length(Name)) as minlength
from MyTable group by pnr) mt2
on mt1.pnr = mt2.pnr and length(mt1.Name) = mt2.minlength