i want to get maximum student interm marks from below table.
Student name Interm1 marks Interm2 marks Interm3 marks
Raj 60 75 89
raju 78 74 67
ram 67 79 65
balaji 91 89 93
My required Output is:
Balaji 93
option:
raju 78
raj 89 etc..
like this i need output.
can any body help me here for this query.
You'll need to first unpivot your data, and then get the MAX value. I prefer using VALUES to unpivot data, rather than the UNPIVOT operator:
SELECT YT.StudentName,
MAX(IM.ItermMark) AS MaxItermMark
FROM YourTable YT
CROSS APPLY(VALUES(Interm1Mark),(Interm2Mark),(Interm3Nark))IM(ItermMark)
GROUP BY StudentName;
Have a look at this. This should do what you want to do
SELECT [Student name], MAX(MaxMark)
FROM
(
SELECT [Student name],
(SELECT MAX(v) FROM (VALUES ([Interm1 marks]), ([Interm2 marks]), ([Interm3 marks])) AS value(v)
) AS [MaxMark]
) AS subquery
GROUP BY [Student name]
Related
Good morning. SQL new guy here seeking some help. I'm attempting to get the AVG of my resultset from a subquery. The subquery works just fine and gives me the resultset I need, but I just cannot get the AVG of the resultset to work. Any guidance would be greatly appreciated.
SELECT AVG(COUNT) FROM
(SELECT COUNT(DISTINCT(table2.item_no))
FROM table1
JOIN table2 ON table1.order_numb = table2.order_numb
WHERE user_so = 'paul'
AND order_date BETWEEN '9/20/2017'AND '9/20/2018'
GROUP BY table1.order_numb);
Here is a sample of the resultset from the subquery on its own that I'm trying to then turn around and get an AVG of:
216
181
163
156
144
144
143
133
129
129
120
114
113
112
112
109
108
104
103
99
98
98
98
98
98
97
97
97
96
96
94
94
94
93
93
I think you want something like this:
SELECT AVG(a_number) FROM
(SELECT COUNT(DISTINCT(table2.item_no)) AS a_number
FROM table1
JOIN table2 ON table1.order_numb = table2.order_numb
WHERE user_so = 'paul'
AND order_date BETWEEN '9/20/2017'AND '9/20/2018'
GROUP BY table1.order_numb) AS the_subquery
I don't have the same tables with data, so here is a cut down working example:
SELECT AVG(a_number) FROM (
SELECT 100 AS a_number
UNION
SELECT 200 AS a_number
UNION
SELECT 300 AS a_number
UNION
SELECT 400 AS a_number
) AS the_subquery
It looks like you were missing that you need to alias the subquery and you want to AVG the alias of the value being returned in the subquery.
update
As per the comment, if you'd like the answer to be rounded to 2 decimal points you will need to CAST it to a different data type, like this:
SELECT ROUND(AVG(CAST(a_number AS FLOAT)), 2) FROM
(SELECT COUNT(DISTINCT(table2.item_no)) AS a_number
FROM table1
JOIN table2 ON table1.order_numb = table2.order_numb
WHERE user_so = 'paul'
AND order_date BETWEEN '9/20/2017'AND '9/20/2018'
GROUP BY table1.order_numb) AS the_subquery
or for others without access to the table:
SELECT ROUND(AVG(CAST(a_number AS FLOAT)), 2) FROM (
SELECT 100 AS a_number
UNION
SELECT 200 AS a_number
UNION
SELECT 300 AS a_number
UNION
SELECT 403 AS a_number
) AS the_subquery
You can read more about how ROUND, AVG, and CAST work here: How do I retrieve decimals when rounding an average in SQL
ID Date Value Average
1 10/5/2017 15 15
2 10/6/2017 25 20
3 10/7/2017 35 25
4 10/8/2017 45 35
5 10/9/2017 55 45
6 10/10/2017 65 55
7 10/11/2017 75 65
If this is my table, I want average to be a computed column and its formula in general is average of previous 3 row's Value column.
(Ex. for 2nd row it is (25+15)/2 )
How can i do such a thing in computed column? Is there any better way to achieve this.
Thanks in advance.
i would go with a view and use avg windows function
select
id,
date,
value,
avg(value) over (order by id)
from table
Updated answer: you could use frames clause like below
Working Demo
;with cte(id,date,val)
as
(
select 1 ,'10/5/2017' , 15 UNION ALL
select 2 ,'10/6/2017' , 25 UNION ALL
select 3 ,'10/7/2017' , 35 UNION ALL
select 4 ,'10/8/2017' , 45 UNION ALL
select 5 ,'10/9/2017' , 55 UNION ALL
select 6 ,'10/10/2017', 65 UNION ALL
select 7 ,'10/11/2017', 75
)
SELECT *,avg(VAL) OVER (ORDER BY id rows between 2 PRECEDING and current row ) FROM CTE
I have a table as following:
[ID] [Name] [Score] [Class]
1 John 90 A
2 Mary 63 A
3 Tom 87 A
4 David 98 A
5 Mary 87 B
6 David 77 B
7 David 73 C
8 Mary 92 C
9 Tom 73 C
10 John 79 C
11 Mary 70 D
12 Jane 85 D
13 David 83 D
I need to get the top 2 persons based on the scores in each class.
My expected output is
[ID] [Name] [Score] [Class]
1 John 90 A
4 David 98 A
5 Mary 87 B
6 David 77 B
8 Mary 92 C
10 John 79 C
12 Jane 85 D
13 David 83 D
Here is what I tried so far but this is not producing the correct results
SELECT *
FROM Student s
WHERE
(
SELECT COUNT(*)
FROM Student f
WHERE f.name = s.name AND
f.score >= s.score
) <= 2
Use ROW_NUMBER:
SELECT
ID, Name, Score, Class
FROM(
SELECT *,
rn = ROW_NUMBER() OVER(PARTITION BY Class ORDER BY Score DESC)
FROM Student
) t
WHERE rn <= 2
DEMO
The specification said... "for each class"
The smallest change that would need to be made to the proposed query to get the the specified results "students with the two highest scores for each class", we'd need to replace one of the predicates in the correlated subquery... matching on [class] rather than on [name]...
SELECT s.*
FROM Student s
WHERE
(
SELECT COUNT(*)
FROM Student f
WHERE f.class = s.class
AND f.score >= s.score
) <= 2
Note that if there are multiple students in the class with the same "highest scores", the query will return all of those students, not just two students for class.
If we specifically want to return "at most two students from each class, the students who have the highest score in each class", we'd need to write the query a little differently.
Given the example data, with no duplicate scores in a class, the results would be the same.
The difference can be demonstrated by adding a row to the example data, for example, adding Saul, having the same "second highest" score as David.
11 Mary 70 D
12 Jane 85 D
13 David 83 D
14 Saul 83 D
The question we need to ask about the specification... should only two students be returned for this class, Jane has the highest score, so obviously return Jane. But David and Saul have the same score. Do we return both, or if we only return one of them, does it matter which one we return?
Should we return three rows:
[ID] [Name] [Score] [Class]
12 Jane 85 D
13 David 83 D
14 Saul 83 D
because those are all of the students with the two highest scores, or should we return just two of the students with the highest scores:
[ID] [Name] [Score] [Class]
12 Jane 85 D
13 David 83 D
or
[ID] [Name] [Score] [Class]
12 Jane 85 D
14 Saul 83 D
Once that question is answered, we can write a query that returns the specified result.
And (obviously) this isn't the only query. There are other query patterns that will return an equivalent result... using either ANSI-standard syntax, or vendor specific extensions.
I want to pull a conversation for a certain order that a person has ever read a message on. For instance:
Order SentTOID ReadBy
A 111 55
A 55 55
A 111 89
B 111 89
C 111 55
C 55 55
D 111 99
D 99 99
Results
A 111 55
A 55 55
A 111 89
C 111 55
C 55 55
My code will only pull all the cases that were read by 55 but I want the whole converstaion.
Order SentTOID ReadBy
A 111 55
A 55 55
C 111 55
C 55 55
Code used.
Select *
from conversation
where readby = 55.
first get Order and apply IN clause
declare #temp table
(Orders nvarchar(7), SentTOID int, ReadBy int)
insert into #temp values ('A',111,55)
insert into #temp values ('A',55 ,55)
insert into #temp values ('A',111,89)
insert into #temp values ('B',111,89)
insert into #temp values ('C',111,55)
insert into #temp values ('C',55 ,55)
insert into #temp values ('D',111,99)
insert into #temp values ('D',99 ,99)
select * from #temp
where Orders in (select Orders from #temp where ReadBy = 55)
RESULT
I have this query that returns Quantity based discount list
with cte([item code],price,discount,rngLow,rngHigh,id) as
(
select 'xxx-xxxxxxx' as [item code],l.t$pric,l.t$disc,lqanp=l.t$qanp,hqanp=h.t$qanp,id = row_number() over(partition by h.t$qanp order by h.t$qanp) from EdiCatalog l
join ediCatalog h on l.comno=h.comno and l.t$cpls=h.t$cpls and l.t$cuno=h.t$cuno and h.t$item=l.t$item and l.t$qanp < h.t$qanp
where l.comno=#comno and l.t$cpls=#cpls and l.t$cuno=#cuno
)
select * from cte
returning result set
How do I transform the result set to this
You can start with this:
SELECT *
FROM cte a
WHERE rngHigh=(
SELECT MIN(rngHigh)
FROM cte b
WHERE b.rngLow=a.rngLow
)
Which will give you this result set:
discount rngLow rngHigh
40 1 9
68 9 23
73 23 47
75 47 299
#Frazz,
Here is what I have now
with little alteration to what you suggested..
SELECT rngLow=case rngLow
when 1 then rnglow
else rnglow+1 end,rngHigh,discount,id
FROM cte a
WHERE rngHigh=(
SELECT MIN(rngHigh)
FROM cte b
WHERE b.rngLow=a.rngLow
)