I have a table that looks like this:
id | SubjectCode | Grade | DateApproved | StudentId
1 SUB123 1.25 1/4/2012 2012-12345
2 SUB123 2.00 1/5/2012 2012-12345
3 SUB123 3.00 1/5/2012 2012-98765
I'm trying to GROUP BY SubjectCode but i'd like it to display the most recent DateApproved so it will look like:
id | SubjectCode | Grade | DateApproved | StudentId
2 SUB123 2.00 1/5/2012 2012-12345
3 SUB123 3.00 1/5/2012 2012-98765
I'm a little bit lost on how to do it?
EDIT:
Ok guys now im on my real PC, sorry for the poorly constructed question.
Here's what I'm actually trying to do:
SELECT GD.GradebookDetailId, G.SubjectCode, G.Description, G.UnitsAcademic, G.UnitsNonAcademic,
GD.Grade, GD.Remarks, G.FacultyName, STR_TO_DATE(G.DateApproved, '%m/%d/%Y %h:%i:%s') AS 'DateAproved'
FROM gradebookdetail GD INNER JOIN gradebook G ON GD.GradebookId=G.GradebookId
WHERE G.DateApproved IS NOT NULL AND G.GradebookType='final' AND StudentIdNumber='2012-12345'
GROUP BY <?????>
ORDER BY G.SubjectCode ASC
Basically, I only want to display the most recent "DateApprove" of a "SubjectCode", so I don't get multiple entries.
Start with this:
select StudentId, max(DateApproved)
from tbl
group by StudentId
Then integrate that to main query:
select *
from tbl
where (StudentId, DateApproved) in
(
select StudentId, max(DateApproved)
from tbl
group by StudentId
)
You can also use this:
select *
from tbl
join (select StudentId, max(DateApproved) as DateApproved
from tbl
group by StudentId)
using (StudentId, DateApproved)
But I prefer tuple testing, it's way neater
Live test: http://www.sqlfiddle.com/#!2/771b8/5
SELECT t2.*
FROM temp t2
INNER JOIN(
SELECT MAX(DateApproved) as MaxDate, StudentId
FROM temp
GROUP BY StudentId
) t1 ON t1.MaxDate = t2.DateApproved and t1.StudentId = t2.StudentId
For users trying this in SQL Server, which at the time of this writing (2020) still does not support tuples, then you can use the following (improving upon another answer here)
Change this:
-- MYSQL
select *
from tbl
where (StudentId, DateApproved) in
(
select StudentId, max(DateApproved)
from tbl
group by StudentId
)
into this:
-- Microsoft SQL Server
select *
from tbl
where concat(StudentId, DateApproved) in
(
select concat(StudentId, max(DateApproved))
from tbl
group by StudentId
)
SELECT *
FROM TheTable a
WHERE NOT EXISTS(SELECT *
FROM TheTable b
WHERE b.StudentCode = a.StudentCode AND b.DateApproved > a.DateApproved)
This was more efficient for me in postgres.
select * from tbl t1 where t1.DateApproved = (select max(t2.DateApproved) from tbl t2 where t2.StudentId = t1.StudentId)
This code works for SQL Server 2016.
select StudentId,
max(DateApproved)
from tbl
group by StudentId
This code will show max and min date approved per student id.
select StudentId,
max(DateApproved),
min(DateApproved)
from tbl
group by StudentId
Related
cust_id
state
1
CA
2
IL
3
SC
1
PA
3
IA
4
MO
5
VA
4
NY
Can any one please advise on SQL Query that return the cust_id that belong to two states as below:
The output should be
cust_id
state
1
CA
1
PA
3
SC
3
IA
4
NY
4
MO
Try the following query
Solution 1
Select * From yourtable
Where Cust_Id In (Select cust_id From yourtable Group By cust_id Having
Count(*) = 2) Order By cust_id,state
Solution 2
With T1 As
(Select cust_id From yourtable Group By cust_id Having Count(*) = 2)
Select T2.* From yourtable T2 Join T1 On T1.cust_id = T2.cust_id O
Order By T2.cust_id,T2.state
SELECT tmp.*
FROM tmp
INNER JOIN (
SELECT cust_id
,COUNT(STATE) s_count
FROM tmp
GROUP BY [cust_id]
) sub
ON tmp.cust_id = sub.cust_id
WHERE sub.s_count = 2
ORDER BY cust_id
,STATE
One simple approach would use a COUNT window function, that will assign the amount of times each "cust_id" occurs in your table. Once you get this value, you can filter out rows whose count is smaller than 2.
WITH cte AS (
SELECT *, COUNT(cust_id) OVER(PARTITION BY cust_id) AS cnt
FROM tab
)
SELECT cust_id,
state
FROM cte
WHERE cnt > 1
Check the demo here.
I have a MySQL table tbl below:
now I run the following query:
SELECT DAY_NUMBER, WEEK_NUMBER, MAX(total_volume)
FROM `tbl`
GROUP BY WEEK_NUMBER
I get the following output:
Everything looks good except for the DAY_NUMBER. The DAY_NUMBER does not reflect the TOTAL_VOLUME from which I query the MAX(TOTAL_VOLUME). If you look at WEEK_NUMBER 31, the MAX(TOTAL_VOLUME) 777 has DAY_NUMBER 7 but the query has 5.
My goal is to have DAY_NUMBER reflect MAX(TOTAL_VOLUME) value DAY_NUMBER.
could you please tell me how do I fix it?
With NOT EXISTS:
SELECT t.*
FROM tbl t
WHERE NOT EXISTS (
SELECT 1 FROM tbl
WHERE WEEK_NUMBER = t.WEEK_NUMBER AND total_volume > t.total_volume
)
Use like this,
SELECT DAY_NUMBER, WEEK_NUMBER, total_volume
FROM `tbl` WHERE total_volume IN(SELECT MAX(total_volume)
FROM `tbl`
GROUP BY WEEK_NUMBER)
You will get Desired output
Do not use GROUP BY for a query where you should be filtering.
I recommend a correlated subquery:
select t.*
from tbl t
where t.total_volume = (select max(t2.total_volume)
from tbl t2
where t2.week_number = t.week_number
);
Alternatively, you can use window functions in MySQL 8+:
select t.*
from (select t.*,
row_number() over (partition by week_number order by volume desc) as seqnum
from tbl t
) t
where seqnum = 1;
With join
drop table if exists t;
create table t
(day_number int, week_number int, value int);
insert into t values
(1,1,10),(2,1,20),
(10,2,20),(11,2,10);
select t.day_number,t.week_number,t.value
from t
join
(select week_number,max(value) m
from t
group by week_number
) w on w.week_number = t.week_number and w.m = t.value;
+------------+-------------+-------+
| day_number | week_number | value |
+------------+-------------+-------+
| 2 | 1 | 20 |
| 10 | 2 | 20 |
+------------+-------------+-------+
2 rows in set (0.00 sec)
In the event of a draw you will get all days which match the max value.
I have a table that has user_id and purchase_id. I want to filter the table so that only users with more than 2 purchases (i.e. there are more than 2 rows for that user in the table). I used count and group by, but it does not work in a way I want.
create view myview as
select user_Id, purchase_id, count(*) as count from mytable group by user_Id;
select user_id, purchase_id from myview where count >2;
But it gives me only users (only one user_id) that has more than 2 purchase and it does not give me all of their purchases. For example if the table looks like this:
user_id purchase_id
1 1212
1 1312
2 1232
1 1321
3 1545
3 4234
My query gives me this :
1 1212
3 1545
But I want this:
1 1212
1 1312
1 1321
3 1545
3 4234
change your last sql like this
select mt.user_id, mt.purchase_id
from myview mv
inner join mytable mt
on mt.user_id=mv.user_id where mv.count >5;
SELECT
*
FROM
mytable mt,
(SELECT user_id, count(*) AS purchase_count FROM mytable GROUP BY user_id) ct
WHERE
mt.user_id = ct.user_id AND ct.purchase_count > 5;
SELECT *
FROM MYTABLE
WHERE USER_ID IN (SELECT USER_ID
FROM MYTABLE
GROUP BY USER_ID
HAVING COUNT(*)>=2)
I tested in my netezza,it works. hopefully, it's also working in mysql
Try GROUP BY with HAVING comment.
SELECT user_Id, purchase_id
FROM mytable
GROUP BY user_Id
HAVING count( * ) >5
As far as I can tell you want to list the user id's and purchase id's of all users that have over 5 purchases.
In order to do this you could do a join on two queries.
For example:
SELECT tblLeft.user_id,
tblLeft.purchase_id
FROM myview tblLeft
JOIN (SELECT user_id,
Count(*) AS purchases
FROM myview
GROUP BY user_id
HAVING purchases > 1) tblRight
ON tblLeft.user_id = tblRight.user_id
The tblRight is essentially a table containing the user_id's of all users with over 5 purchases.
We then do a select (tblLeft) and join it on the tbl right, ensuring only customers with over 5 purchases remain.
This question already has an answer here:
how to get count of values in mysql [closed]
(1 answer)
Closed 6 years ago.
I have a table user_places like this:
user_id recorded_date place_visited
2 2016-04-05 NY
2 2016-04-07 UK
2 2016-04-08 UK
2 2016-04-08 UK
3 2016-04-08 AUS
3 2016-04-09 AUS
2 2016-04-15 NY
3 2016-04-15 CAN
I am trying to get the place visited in last recorded_date of user and name of the place that he has visited the most.
i.e
user_id recorded_date_last place_visited_most last_visited_place
2 2016-04-15 UK NY
3 2016-04-15 AUS CAN
Here's a way using a subquery:
select * ,
(select place_visited from mytable t2
where t2.user_id = t1.user_id
group by place_visited
order by count(*) desc
limit 1) place_visited_most
from mytable t1
where recorded_date = (select max(recorded_date) from mytable)
http://sqlfiddle.com/#!9/ad351/4
Here's an untested stab at it. I'm not as familiar with MySQL so there may be other approaches that work better. This is a set-based method that avoids using limit and order by.
select t.user_id, t.place_visited, modex.cnt, maxd.max_recorded_date
from
T t inner join
(
select user_id, max(recorded_date) as max_recorded_date from T
group by user_id
) maxd
on maxd.user_id = t.user_id
inner join
(
select user_id, max(cnt) as max_cnt
from
(
select user_id, count(*) as cnt from T
group by user_id, place_visited
) counts
group by user_id
) maxc
on maxc.user_id = t.user_id
inner join
(
select user_id, cnt, min(place_visited) as place_most_visited
from
(
select user_id, place_visited, count(*) as cnt from T
group by user_id, place_visited
) break_ties
group by user_id, cnt
) modex
on modex.user_id = maxd.user_id
and maxc.max_cnt = modex.cnt and modex.place_most_visited = t.place_visited
Since you could have ties for the mode of place_visited I just kept the lowest alphabetically. I did assume that there would be no ties for recorded_date though.
I have the following data in a table :-
Student Subject Marks
Peter English 85
Peter Maths 79
Peter Science 80
Milind English 71
Milind Maths 95
Milind Science 89
I want to write a query which will give me for each student, the subject in which s/he scored max. In this case, it will be
Peter English
Milind Maths
Thanks in advance for the help.
Milind.
You could do like below:
SELECT
t1.Student, t1.Subject
FROM your_table t1
INNER JOIN (
SELECT MAX(Marks) AS max_marks, Subject
FROM your_table
GROUP BY Subject
) t2 ON t1.Subject = t2.Subject AND t1.Marks = t2.max_marks
This is what you can do , but in case a student has 2 max marks it will list only one of them
select
t1.Student,
t1.Subject,
t2.Marks from
table_name t1
join
(
select
Student,
max(Marks) as Marks
from table_name
group by Student
)t2
on t2.Student = t1.Student AND t2.Marks = t1.Marks
group by t1.Student;
If you need both max() marks subjects to be displayed in case there are, then the last group by needs to be changed to
group by t1.Student,t1.Subject;
Here is a demo to illustrate both of them.
there are few ways to do, you can try this solution
select
t1.*
from
your_table t1
left join your_table t2 on t1.Student = t2.Student and t1.Marks < t2.Marks
where
t2.Marks is null
Try this, this should work : Please revert in case of any Clarifications.
"StudentMarks is the name of the table"
;With MaxMarks as
(
Select Name, Subject_, Marks as Highmarks from StudentMarks
Group by Name, Subject_, Marks
)
Select * from MaxMarks where Highmarks in
(Select Max(Highmarks) from MaxMarks
Group by Name
)
You can combine multiple queries, so something like this:
SELECT * FROM students WHERE Student='Peter' AND Marks=( SELECT MAX(Marks) WHERE Student='Peter' )
Note that this is untested.