Getting a row with two group by constraints - sql

I have a table
TIMESTAMP ID Name
5/30/2016 11:45 1 Ben
5/30/2016 11:45 2 Ben
5/30/2016 23:15 2 Ben
5/30/2016 7:30 1 Peter
5/30/2016 6:05 1 Peter
5/30/2016 14:40 2 May
5/30/2016 1:05 1 May
Now, I need to get the MIN timestamp for each distinct Name.
Then if there are more than one MIN entry, choose the one with the MAX ID.
So the result should be
TIMESTAMP ID Name
5/30/2016 11:45 2 Ben
5/30/2016 6:05 1 Peter
5/30/2016 1:05 1 May
I tried using the query below:
SELECT MIN(TIMESTAMP),NAME FROM TBLSAMPLE WHERE TIMESTAMP BETWEEN TO_DATE('5/30/2016', 'MM/DD/YYYY' ) AND TO_DATE('5/30/2016', 'MM/DD/YYYY' ) + 1
GROUP BY NAME
and I could get the minimum time. But once I add in MAX(ID) the result return an entry that does not match any of the rows.
Your help are really appreciated.

You can do this with row_number():
select t.*
from (select t.*,
row_number() over (partition by name order by timestamp asc, id desc) as seqnum
from tblsample t
) t
where seqnum = 1;
Your question doesn't specify a condition on the dates. But if you want to add a where clause, then add it to the subquery.

Related

find the youngest student from date

I have the below table:
name id DOB marks
rk 2 2006-02-03 00:00:00.000 30
mk 3 2006-07-07 00:00:00.000 30
pk 4 2006-04-09 00:00:00.000 30
sk 5 2006-05-03 00:00:00.000 30
fk 6 2006-08-09 00:00:00.000 30
nk 7 2007-08-06 00:00:00.000 30
How can I find the youngest student?
You can order your table by descending date of birth and then filter the first result only, which in SQL Server can be done with
select top 1 *
from yourTable
order by DOB desc
Looks like you just need the latest date of birth (assuming DOB is date of birth):
select max(dob) from yourtable
Then your query would be:
select name as youngestStudent, dob as dateOfBirth
from yourtable
where dob = (select max(dob) from yourtable)
It's simple. According to your given data "nk" is the youngest student, so you can use the following query :
select * from yourtable
where dob = (select max(dob) from yourtable)

Get MAX count but keep the repeated calculated value if highest

I have the following table, I am using SQL Server 2008
BayNo FixDateTime FixType
1 04/05/2015 16:15:00 tyre change
1 12/05/2015 00:15:00 oil change
1 12/05/2015 08:15:00 engine tuning
1 04/05/2016 08:11:00 car tuning
2 13/05/2015 19:30:00 puncture
2 14/05/2015 08:00:00 light repair
2 15/05/2015 10:30:00 super op
2 20/05/2015 12:30:00 wiper change
2 12/05/2016 09:30:00 denting
2 12/05/2016 10:30:00 wiper repair
2 12/06/2016 10:30:00 exhaust repair
4 12/05/2016 05:30:00 stereo unlock
4 17/05/2016 15:05:00 door handle repair
on any given day need do find the highest number of fixes made on a given bay number, and if that calculated number is repeated then it should also appear in the resultset
so would like to see the result set as follows
BayNo FixDateTime noOfFixes
1 12/05/2015 00:15:00 2
2 12/05/2016 09:30:00 2
4 12/05/2016 05:30:00 1
4 17/05/2016 15:05:00 1
I manage to get the counts of each but struggling to get the max and keep the highest calculated repeated value. can someone help please
Use window functions.
Get the count for each day by bayno and also find the min fixdatetime for each day per bayno.
Then use dense_rank to compute the highest ranked row for each bayno based on the number of fixes.
Finally get the highest ranked rows.
select distinct bayno,minfixdatetime,no_of_fixes
from (
select bayno,minfixdatetime,no_of_fixes
,dense_rank() over(partition by bayno order by no_of_fixes desc) rnk
from (
select t.*,
count(*) over(partition by bayno,cast(fixdatetime as date)) no_of_fixes,
min(fixdatetime) over(partition by bayno,cast(fixdatetime as date)) minfixdatetime
from tablename t
) x
) y
where rnk = 1
Sample Demo
You are looking for rank() or dense_rank(). I would right the query like this:
select bayno, thedate, numFixes
from (select bayno, cast(fixdatetime) as date) as thedate,
count(*) as numFixes,
rank() over (partition by cast(fixdatetime as date) order by count(*) desc) as seqnum
from t
group by bayno, cast(fixdatetime as date)
) b
where seqnum = 1;
Note that this returns the date in question. The date does not have a time component.

SQL Show All column by one column distinct

I have a table with duplicate item's ...
I need show the list of all columns without duplicate item's
for example i have this table:
ID CODE RANK TIME
1 12345 2 10:00
2 12345 2 11:00
3 98765 3 20:00
4 98765 3 22:00
5 66666 2 10:00
6 55555 5 11:00
result , i need :
ID CODE RANK TIME
1 12345 2 10:00
3 98765 3 20:00
5 66666 2 10:00
6 55555 5 11:00
The time column in not Important , only one of them most be show ...
try this:
SELECT * FROM myTable WHERE ID IN(SELECT MIN(ID) FROM myTable GROUP BY Code)
If there is no specific way the ID should show (just like the time column), and the ID and TIME column are always sorted that way,this should work.
SELECT MIN(id), code, rank, MIN(time)
FROM table
GROUP BY code, rank
So you only want rows where the CODE is not duplicated in the table.
SELECT "CODE"
FROM table1
GROUP BY "CODE"
HAVING COUNT(*) = 1
This will return the distinct CODE-s. Based on them - as they are unique - you can self-join it to fetch the whole rows:
SELECT *
FROM table1
WHERE "CODE" IN (
SELECT "CODE"
FROM table1
GROUP BY "CODE"
HAVING COUNT(*) = 1
)
I think you are looking for the DISTINCT clause;
SELECT DISTINCT
column_1,
column_2
FROM
tbl_name;

SQL Select the Columnid with a max column group by one column

I think this question is already answered but it didn't satisfy my question.
I'd like to select the id/s of the names group by the latest date value (MAX) in my table. Using a group by column Name and group by column Date, I must get the ID, Name, Date.
Here is my table
ID Name Date
---------------------------------------
1 Brent 2012-02-17
2 Ash 2012-08-02
3 Brent 2012-08-15
4 Harold 2012-09-30
5 Margaret 2012-10-10
6 Ash 2012-12-01
7 Harold 2013-02-14
8 Ash 2012-01-01
9 Brent 2013-05-11
Output must be:
ID Name Date
---------------------------------------
5 Margaret 2012-10-10
6 Ash 2012-12-01
7 Harold 2013-02-14
9 Brent 2013-05-11
I try this statement:
SELECT
[ID], [Name], MAX([Date]) as [Date]
FROM
[SampleTable]
GROUP BY
[Name]
But I get this error:
Column 'ID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
you can use Window Function such as ROW_NUMBER()
SELECT a.ID, a.Name, a.Date
FROM
(
SELECT ID, Name, Date,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DATE DESC) rn
FROM TableName
) a
WHERE a.rn = 1
if ID and Name is the same for every group, you can simply add Name in the GROUP BY clause.
GROUP BY ID, Name

SQL: Return only first occurrence

I seldomly use SQL and I cannot find anything similar in my archive so I'm asking this simple query question: I need a query which one returns personID and only the first seenTime
Records:
seenID | personID | seenTime
108 3 13:34
109 2 13:56
110 3 14:22
111 3 14:31
112 4 15:04
113 2 15:52
Wanted result:
personID | seenTime
3 13:34
2 13:56
4 15:04
That's what I did & failed:
SELECT t.attendanceID, t.seenPersonID, t.seenTime
(SELECT ROW_NUMBER() OVER (PARTITION BY seenID ORDER BY seenID) AS RowNo,
seenID,
seenPersonID,
seenTime
FROM personAttendances) t
WHERE t.RowNo=1
P.S: Notice SQL CE 4
If your seenTime increases as seenID increases:
select personID, min(seenTime) as seenTime
from personAttendances
group by personID
Update for another case:
If this is not the case, and you really want the seenTime that corresponds with the minimum seenID (assuming seenID is unique):
select a.personID, a.seenTime
from personAttendances as a
join (
-- Get the min seenID for each personID
select personID, min(seenID) as seenID
from personAttendances
group by personID
) as b on a.personID = b.personID
where a.seenID = b.seenID
You're making it way too difficult:
select personID, min(seenTime)
from personAttendances
group by personID
for PostgreSQL there is DISTINCT ON
You need to order by seen time not by seen id:
PARTITION BY seenID ORDER BY seenTime
Add this to your SQL:
and where not exists
(select 1 from personAttendances t2
where t.personID=t2.personID
and t2.seenID < t.seenID)