I am new to SQL Server, I have 3 tables consider an employee table
empid
name
location
1
abc
USA
2
efg
UK
Another table named location-table
location
holidaycode
uk
uk1
usa
usa1
And also holidaytable:
holiday-code
date
type
uk1
2022-01-01
LM
uk1
2022-01-01
RMC
Expected result is:
empid
location
holidaycode
date
type 1
2
uk
uk1
2022-01-01
RMC
suppose I query the tables based on empid and date say ,the holidays available for empid 2 from a particular from date such that on a particular day (2022-01-01) I have LM and RMC on that day , I need only RMC ,if RMC is not available else LMC.
Please try this
select e.empid, e.location, h.holidaycode, [date], max([type])
from employee e inner join location_table l
on e.location=l.location
inner join holidaytable h
on l.holidaycode=h.holidaycode
where e.empid=2 and h.[date]='2022-01-01'
group by e.empid, e.location, h.holidaycode, [date]
Example:
Schema and insert statements:
create table employee(empid int, name varchar(50), location varchar(50));
insert into employee values(1, 'abc', 'USA');
insert into employee values(2, 'efg', 'UK');
create table location_table(location varchar(50),holidaycode varchar(50));
insert into location_table values('uk','uk1');
insert into location_table values('usa','usa1');
create table holidaytable(holidaycode varchar(50), [date] date, [type] varchar(50));
insert into holidaytable values('uk1', '2022-01-01', 'LM');
insert into holidaytable values('uk1', '2022-01-01', 'RMC');
Query:
select e.empid, e.location, h.holidaycode, [date], max([type]) [type 1]
from employee e inner join location_table l
on e.location=l.location
inner join holidaytable h
on l.holidaycode=h.holidaycode
where e.empid=2 and h.[date]='2022-01-01'
group by e.empid, e.location, h.holidaycode, [date]
Output:
empid
location
holidaycode
date
type 1
2
UK
uk1
2022-01-01
RMC
db<>fiddle here
You can use ROW_NUMBER to get only the first row of each grouping.
Either do ORDER BY type DESC or use ORDER BY CASE WHEN type = 'RMC' THEN 1 ELSE 2 END
SELECT
e.empid,
e.location,
l.holidaycode,
h.date,
h.type
FROM employee e
JOIN location l ON l.location = e.location
JOIN (
SELECT *,
rn = ROW_NUMBER() OVER (PARTITION BY h.holidaycode, h.date ORDER BY h.type DESC)
FROM holiday h
) h ON h.holidaycode = l.holidaycode AND h.rn = 1
WHERE h.date = '2022-01-01';
db<>fiddle
Related
I am attempting the group by date of an attendance timestamp and at the same time list all employees of the grouped date. And regardless if there is entry in the attendance, I'd like to list all available employee.
Here is my attempt to produce the query, but it lacks listing all the employees for every generated date.
Please refer to my attempted sql code:
https://dbfiddle.uk/?rdbms=postgres_13&fiddle=a971a7ac01fb2f4bc7458983c40a24bf
SELECT
a.created_at::date as created_date,
a.employee_id,
e.name,
e.division_id,
MIN(a.created_at::time) FILTER (WHERE a.activity_type = 1) as min_time_in,
MAX(a.created_at::time) FILTER (WHERE a.activity_type = 2) as max_time_out
FROM
attendance a
LEFT JOIN employee e on e.id = a.employee_id
GROUP BY created_date, a.employee_id, e.name, e.division_id
ORDER BY created_date, a.employee_id
the result shows like this:
created_date employee_id name division_id min_time_in max_time_out
2020-11-18 1 John 1 07:10:25 20:01:05
2020-11-18 2 Amber 2 07:30:25 19:10:25
2020-11-18 3 Mike 1 07:50:25 19:22:38
2020-11-19 1 John 1 07:11:23 23:21:53
However, my goal is to list all employees and group the employee_id records by date. regardless if there is attendance by the employee, it should show a row of the date. How can I generate a query that produce like below:
created_date employee_id name division_id min_time_in max_time_out
2020-11-18 1 John 1 07:10:25 20:01:05
2020-11-18 2 Amber 2 07:30:25 19:10:25
2020-11-18 3 Mike 1 07:50:25 19:22:38
2020-11-18 4 Jimmy 1 null null
2020-11-18 5 Kathy 2 null null
2020-11-19 1 John 1 07:11:23 23:21:53
2020-11-19 2 Amber 2 null null
2020-11-19 3 Mike 1 null null
2020-11-19 4 Jimmy 1 null null
2020-11-19 5 Kathy 2 null null
This should work:
SELECT
d::date AS created_date
, e.id
, e.name
, e.division_id
, MIN(a.created_at::time) FILTER (WHERE a.activity_type = 1) as min_time_in
, MAX(a.created_at::time) FILTER (WHERE a.activity_type = 2) as max_time_out
FROM (SELECT MIN(created_at), MAX(created_at) FROM attendance) AS r(startdate,enddate)
, generate_series(
startdate::timestamp,
enddate::timestamp,
interval '1 day') g(d)
CROSS JOIN employee e
LEFT JOIN attendance a ON a.created_at::date = d::date AND e.id = a.employee_id
GROUP BY
created_date
, e.id
, e.name
, e.division_id
ORDER BY
created_date
, e.id;
edit: id from employee selected, instead of employee_id
Just cross join the distinct dates from your attendance table with employee table.
You can try like below:
select
a1. date,
e.id,
e.name,
e.division_id,
MIN(a.created_at::time) FILTER (WHERE a.activity_type = 1 ) as min_time_in,
MAX(a.created_at::time) FILTER (WHERE a.activity_type = 2) as max_time_out
from
employee e left join (select distinct date(created_at) "date" from attendance ) a1 on true
left JOIN attendance a on e.id=a.employee_id and date(a.created_at)=a1.date
group by 1,2,3,4
order by 1,2
Note: left join on true is equivalent to cross join
DEMO
UPDATE:
If you want the output for all dates between min date and max date.
with cte as (select min(created_at)::date "mindate", max(created_at)::date "maxdate" from attendance )
select
a1. date,
e.id,
e.name,
e.division_id,
MIN(a.created_at::time) FILTER (WHERE a.activity_type = 1 ) as min_time_in,
MAX(a.created_at::time) FILTER (WHERE a.activity_type = 2) as max_time_out
from
employee e
left join (select g.date from cte, generate_series(cte.mindate,cte.maxdate,interval '1 day') g(date) ) a1 on true
left JOIN attendance a on e.id=a.employee_id and date(a.created_at)=a1.date
group by 1,2,3,4
order by 1,2
DEMO
I have a Members table like this:
PersonID FirstName Address City date
---------------------------------------------------------
3 Rasanga Skagen 21 South 2019-01-05
and a Persons table:
PersonID FirstName Address City date
-------------------------------------------------------
3 Rasanga Skagen 21 South 2019-01-06
1 Tom B. Skagen 21 Colombo 2018-01-07
2 Tom B. Skagen 21 Colombo 2019-01-05
I want to get Persons that do not exists in Members table using the FirstName column. For that I'm using this query:
SELECT *
FROM Persons p
WHERE NOT EXISTS (SELECT * FROM Members m WHERE m.FirstName = p.FirstName)
When I execute above query I'm getting same FirstName and 2 records but my requirement is if there's 2 records for same name retrieve latest record using date column. Therefore above scenario it should be Tom B. with 2018-01-07 record. If both records have same date should retrieve 1 record from 2 records.
Can somebody explain how to do this?
You can use the left join and checking the Members.PersonId is null.
create table Members(PersonID int
, FirstName varchar(20)
, Address varchar(50)
, City varchar(50)
, Dtdate date)
insert into Members values
(3, 'Rasanga', 'Skagen 21', 'South', '2019-01-05')
Create table Persons(PersonID int
, FirstName varchar(20)
, Address varchar(50)
, City varchar(50)
, Dtdate date)
insert into Persons values
(3, 'Rasanga', 'Skagen 21', 'South', '2019-01-06'),
(1, 'Tom B.', 'Skagen 21', 'Colombo', '2018-01-07'),
(2, 'Tom B.', 'Skagen 21', 'Colombo', '2019-01-05')
Select Persons.* from Persons
left join Members on Persons.PersonID = Members.PersonID
where Members.PersonId is null
Demo
Using the not exists you can check as shown below.
SELECT Persons.*
FROM Persons
WHERE NOT EXISTS (SELECT 1
FROM Members
WHERE Persons.PersonID = Members.PersonID)
Using the in operator
SELECT * FROM Persons
WHERE PersonID NOT IN (
SELECT PersonID FROM Members
)
To get the unique records based on the first name and date you can use the following query using ROW_NUMBER() function.
;WITH cte
AS (
SELECT Persons.*
,ROW_NUMBER() OVER (
PARTITION BY Persons.FirstName ORDER BY Persons.Dtdate DESC
) AS RN
FROM Persons
LEFT JOIN Members ON Persons.PersonID = Members.PersonID
WHERE Members.PersonId IS NULL )
SELECT *
FROM CTE
WHERE RN = 1
Output
PersonID FirstName Address City Dtdate RN
----------------------------------------------------------
2 Tom B. Skagen 21 Colombo 2019-01-05 1
You could use a window function as
SELECT T.PersonID,
T.FirstName,
T.Address,
T.City,
T.[Date]
FROM
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY FirstName ORDER BY [Date] DESC) RN
FROM Persons
) T
WHERE NOT EXISTS
(
SELECT 1
FROM Members
WHERE FirstName = T.FirstName
) AND T.RN = 1;
Here is a db<>fiddle
We have 3 tables in Oracle 11g, need to left join them and return the data in single row different columns with count of the join, Is there any way We can acheive the same.
Example:
Table1: (Employee_Data)
Table2: (Employee_Address)
Table3: (Employee_Role)
Expected Result:
Mack has 2 addresses and 2 roles so Emp_Addr_Count is 2, Emp_Role_Count is 2 and the related data is in same row different column.
Kindly note that EMP_ID is unique in Employee_Data table and Employee_Address and Employee_Role could be multiple or zero for a Employee.
Thanks in Advance.
Try this:
SELECT E.Emp_Id
,E.Emp_Name
,E.Emp_Age
,NVL(MAX(EA.RN),0)Addr_Count
,NVL(MAX(CASE WHEN EA.RN = 1 THEN EA.Emp_Address END),' ')Emp_Address_1
,NVL(MAX(CASE WHEN EA.RN = 1 THEN EA.Emp_City END),' ')Emp_City_1
,NVL(MAX(CASE WHEN EA.RN = 2 THEN EA.Emp_Address END),' ')Emp_Address_2
,NVL(MAX(CASE WHEN EA.RN = 2 THEN EA.Emp_City END),' ')Emp_City_2
,NVL(MAX(ER.RN1),0)Role_Count
,NVL(MAX(CASE WHEN ER.RN1 = 1 THEN ER.Emp_task END),' ')Emp_task_1
,NVL(MAX(CASE WHEN ER.RN1 = 2 THEN ER.Emp_task END),' ')Emp_task_2 FROM Employee_Data E JOIN(
SELECT Emp_Id
,ROW_NUMBER() OVER(PARTITION BY Emp_Id ORDER BY Emp_City desc) RN
,Emp_City
,Emp_Address
FROM Employee_Address
)EA ON EA.Emp_Id = E.Emp_Id left JOIN(
SELECT Emp_Id
,ROW_NUMBER() OVER(PARTITION BY Emp_Id ORDER BY Emp_Task) RN1
,Emp_task
FROM Employee_Role
)ER ON ER.Emp_Id = E.Emp_Id GROUP BY E.Emp_Id,E.Emp_Name,E.Emp_Age
Output:
EMP_ID EMP_NAME EMP_AGE ADDR_COUNT EMP_ADDRESS_1 EMP_CITY_1 EMP_ADDRESS_2 EMP_CITY_2 ROLE_COUNT EMP_TASK_1 EMP_TASK_2
1 MACK 45 2 HOME PARADISE MUM TINDER ONCLAVE DEL 2 Manage Task Resource Manage
2 JACK 30 1 BLUE PLAZA MUM 1 Code
3 ANGEL 27 1 HOME PARADISE MUM 0
You can join them as in the following statement :
WITH t AS
(
SELECT d.*, a.emp_address, a.emp_city, r.emp_task
FROM employee_data d
JOIN employee_address a on ( d.emp_id = a.emp_id )
FULL OUTER JOIN employee_role r on ( d.emp_id = r.emp_id )
)
SELECT emp_id, emp_name, emp_age, count(distinct emp_address) emp_addr_count,
min(emp_address) emp_address_1, max(emp_city) emp_city_1,
decode(min(emp_address),max(emp_address),null,max(emp_address)) emp_address_2,
decode(min(emp_city),max(emp_city),null,min(emp_city)) emp_city_2,
count(distinct emp_task) emp_role_count, min(emp_task) emp_task_1,
decode(min(emp_task),max(emp_task),null,max(emp_task)) emp_task_2
FROM t
GROUP BY emp_id, emp_name, emp_age
ORDER BY emp_id;
SQL Fiddle Demo
First of all I would like to thank the friends who helped this complex and difficult query.
I have three tables
Table 1
StaffId FirstName LastName staffType
---------------------------------------
1 Adam Sorme Student
2 Lara Sandra Teacher
3 Jack Jones Student
Table 2
GateId GateName
---------------------------------------
1 frontDoor
2 superDoor
Table 3
Id transitionDate GateId StaffId
---------------------------------------
1 2018-01-1 08:00:00 1 1
2 2018-01-1 10:00:00 2 1
3 2018-01-1 20:00:00 2 1
4 2018-01-2 07:00:00 1 2
5 2018-01-2 10:00:00 1 3
6 2018-01-9 12:00:00 2 2
I want the first and last movements of students for each day. Value must be set to null if no movement is available between the specified dates
transitionDate> '2018-01-1 00:00:00 000'
and transitionDate< '2018-01-03 00:00:00 000'
OUTPUT:
Id Date MinTransitionDate MaxTransitionDate FirstGateName LastGateName StaffId StaffType
1 2018-01-01 2018-01-1 08:00:00 2018-01-1 20:00:00 frontDoor superDoor 1 Student
2 2018-01-01 null null null null 3 student
3 2018-01-02 null null null null 1 student
4 2018-01-02 2018-01-2 10:00:00 null frontDoor null 3 student
The following query is partially working.
select
q.*,
g1.GateName as first_gate_name,
g2.GateName as last_gate_name
from
(
select s.staffId, d.dte,
min(t.transitionDate) as min_Date,
max_Date= case when count(1)>1 then max(t.transitionDate) else null end,
max(case when seqnum_asc = 1 then gateId end) as first_gateid,
max(case when seqnum_desc = 1 then gateId end) as last_gateid
from (select s.* from Staff s where stafftype = 'Student') s cross join
(select distinct cast(transitionDate as date) as dte from Transitions) d left join
(select t.*,
row_number() over (partition by StaffId, cast(transitionDate as date) order by transitionDate) as seqnum_asc,
row_number() over (partition by StaffId, cast(transitionDate as date) order by transitionDate desc) as seqnum_desc
from Transitions t
) t
on cast(t.transitiondate as date) = d.dte and
t.staffId = s.staffId and
1 in (t.seqnum_asc, t.seqnum_desc)
group by s.staffId, d.dte
) q
left join Gates g1 on g1.gateId = q.first_gateid
left join Gates g2 on g2.gateId = q.last_gateid
see working demo
Problem : max_date in 4. row is empty. I want the value of last_gateid to be null. Can you help me?
screenshot 4. row
https://cdn.pbrd.co/images/H7vyu31.png
A quick fix would be replacing this line
max(case when seqnum_desc = 1 then gateId end) as last_gateid
with
max(case when (seqnum_desc = 1 and seqnum_asc != 1) then t.gateId end) as last_gateid
It is obvious that some one helped you write the query and you gave him more explanation of the problem , what i did is tweaking the query you provided and used the same logic to give you the desired output although i would prefer to rewrite it in a more understandable way :
select
q.*,
g1.GateName as first_gate_name,
g2.GateName as last_gate_name
from
(
select s.staffId, d.dte,
min(t.transitionDate) as min_Date,
max_Date= case when count(1)>1 then max(t.transitionDate) else null end,
max(case when seqnum_asc = 1 then gateId end) as first_gateid,
case when count(1)>1 then MAX(gateId) end as last_gateid
from (select s.* from Staff s where stafftype = 'Student') s cross join
(select distinct cast(transitionDate as date) as dte from Transitions) d left join
(select t.*,
row_number() over (partition by StaffId, cast(transitionDate as date) order by transitionDate) as seqnum_asc,
row_number() over (partition by StaffId, cast(transitionDate as date) order by transitionDate desc) as seqnum_desc
from Transitions t
) t
on cast(t.transitiondate as date) = d.dte and
t.staffId = s.staffId and
1 in (t.seqnum_asc, t.seqnum_desc)
group by s.staffId, d.dte
) q
left join Gates g1 on g1.gateId = q.first_gateid
left join Gates g2 on g2.gateId = q.last_gateid
IF OBJECT_ID('dbo.Staff') IS NOT NULL DROP TABLE Staff
create table Staff (StaffId int, FirstName varchar(20), LastName
varchar(20), staffType varchar(20))
insert into Staff values
(1, 'Adam', 'Sorme', 'Student'),
(2, 'Lara', 'Sandra', 'Teacher'),
(3, 'Jack', 'Jones', 'Student')
IF OBJECT_ID('dbo.Gates') IS NOT NULL DROP TABLE Gates
create table Gates (GateId int, GateName varchar(20))
insert into Gates values
(1, 'frontDoor'),
(2, 'backDoor')
IF OBJECT_ID('dbo.Transitions') IS NOT NULL DROP TABLE Transitions
create table Transitions (Id int, transitionDate datetime, GateId int,
StaffId int)
insert into Transitions values
(1, '2018-01-1 08:00:00', 1, 1),
(2, '2018-01-1 10:00:00', 2, 1),
(3, '2018-01-1 20:00:00', 2, 1),
(4, '2018-01-2 07:00:00', 1, 2),
(5, '2018-01-2 10:00:00', 2, 3),
(6, '2018-01-9 12:00:00', 2, 2)
--select * from Transitions
DECLARE #Datefrom DATETIME = '2018-01-01'
DECLARE #DateTo DATETIME = '2018-01-03'
----1. If the transition table itself is not reliable meaning there
--could be imports and the maxID could be for a lesser datetime
IF OBJECT_ID('tempdb..#Transitions') IS NOT NULL DROP TABLE
#Transitions
SELECT *, [GateSortID] = RANK() OVER (PARTITION BY StaffID ORDER BY
StaffID,GateID,TransitionDate)
INTO #Transitions
FROM Transitions
----2.Based on above temp table get first and last dates
IF OBJECT_ID('tempdb..#FirstandLastDates') IS NOT NULL DROP TABLE
#FirstandLastDates
SELECT T.StaffId,
[FirstDate] = FirstDate.transitionDate,
[LastDate] = LastDate.transitionDate
INTO #FirstandLastDates
FROM #Transitions T
JOIN
(
SELECT TT.StaffId,
[MinGateSortID] = MIN(GateSortID),
TT.GateID,
G.transitionDate
FROM #Transitions TT
JOIN Transitions G
ON TT.StaffId = G.StaffId
AND TT.Id = G.ID
AND TT.GateId = G.GateId
WHERE GateSortID = 1-- MIN VALUE WILL ALWAYS BE 1
GROUP BY TT.StaffID,TT.GateID,G.transitionDate
)FirstDate --lol!!
ON T.StaffID= FirstDate.StaffID
LEFT JOIN
(
SELECT TT.StaffId, TT.GateId, G.TransitionDate
FROM #Transitions TT
JOIN #Transitions G
ON TT.StaffId = G.StaffId
AND TT.Id = G.ID
AND TT.GateId = G.GateId
JOIN
(
SELECT StaffID,
[MaxGateSortID] = MAX(GateSortID)
FROM #Transitions TT
WHERE GateSortID <> 1 -- SO THAT IF THE PERSON HAS NOT --CLOCKED OUT YET ONLY CLOCKED IN DO NOT CONSIDER THAT THE
--GATES ARE SAME
GROUP BY StaffID
) LastGate1
ON TT.StaffId = LastGate1.StaffId
AND TT.GateSortID = LastGate1.MaxGateSortID
)LastDate
ON T.StaffId = LastDate.StaffId
GROUP BY T.StaffId,FirstDate.transitionDate,LastDate.transitionDate
----3.Based on above temp table get first and last transition gates
IF OBJECT_ID('tempdb..#FirstandLastGates') IS NOT NULL DROP TABLE
#FirstandLastGates
SELECT T.StaffId,
[FirstGate] = FirstGate.GateName,
[LastGate] = LastGate.GateName
INTO #FirstandLastGates
FROM #Transitions T
JOIN
(
SELECT StaffID,
[MinGateSortID] = MIN(GateSortID),
TT.GateID,
GateName
FROM #Transitions TT
JOIN Gates G
ON TT.GateId = G.GateId
WHERE GateSortID = 1-- MIN VALUE WILL ALWAYS BE 1
--AND TT.transitionDate BETWEEN #Datefrom AND #DateTo
GROUP BY StaffID,TT.GateID,GateName
)FirstGate
ON T.StaffID= FirstGate.StaffID
LEFT JOIN
(
SELECT TT.StaffId, TT.GateId, G.GateName
FROM #Transitions TT
JOIN Gates G
ON TT.GateId = G.GateId
JOIN
(
SELECT StaffID,
[MaxGateSortID] = MAX(GateSortID)
FROM #Transitions TT
WHERE GateSortID <> 1 -- SO THAT IF THE PERSON HAS NOT CLOCKED
-- OUT YET ONLY CLOCKED IN DO NOT CONSIDER THAT THE GATES ARE --SAME
--AND TT.transitionDate BETWEEN #Datefrom AND #DateTo
GROUP BY StaffID
) LastGate1
ON TT.StaffId = LastGate1.StaffId
AND TT.GateSortID = LastGate1.MaxGateSortID
)LastGate
ON T.StaffId = LastGate.StaffId
GROUP BY T.StaffId,FirstGate.GateName,LastGate.GateName
--MAIN OUTPUT
SELECT DISTINCT --t.Id,
--t.transitionDate,
[MinTransitionDate] = D.FirstDate,
[MaxTransitionDate] = D.LastDate,
[FirstGateName] = G.FirstGate,
[LastGateName] = G.LastGate,
T.[StaffId],
S.StaffType
from Staff S
JOIN #Transitions T
ON S.StaffId = T.StaffId
JOIN #FirstandLastDates D
ON T.StaffId = D.StaffId
JOIN #FirstandLastGates G
ON T.StaffId = G.StaffId
GROUP BY t.Id, D.FirstDate, D.LastDate, G.FirstGate,G.LastGate,T.[StaffId],
S.StaffType
Data:
Name | Score | Date
==
John | 10 | 09/01/2012
John | 20 | 09/01/2012
John | 5 | 09/01/2012
Frank | 20 | 11/01/2012
I want to run an SQL statement that will pull only the highest score from each day only, so I don't want three scores from one date, only the highest. So the return I'd like from SQL would be:
John | 20 | 09/01/2012
Frank | 20 | 11/01/2012
Is it possible to do this via SQL, currently I can do it after pulling everything by checking dates. But would be great if it's possible to do it direct from the DB.
I have tried a few solutions but as Date and Score aren't distinct, as I want the highest I am unsure of where to proceed. The SQL is being used with a MS Access database.
Here's a complete example. I did it in Oracle, so you might have to tweak the syntax a bit for Access.
CREATE TABLE tbl1 (NAME VARCHAR2(100), score INT, Dt DATE);
INSERT INTO tbl1 VALUES ('John',10,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('John',20,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('John',5,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('Harry',15,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('Frank',20,to_date('20121101','YYYYMMDD'));
select a.dt
, b.name
, a.score
FROM (SELECT dt
, MAX(score) score
FROM tbl1
GROUP BY dt) a
, (SELECT NAME
, dt
, MAX(score) score
FROM tbl1
GROUP BY name, dt) b
WHERE a.dt = b.dt
AND a.score = b.score
Output:
1 11/1/2012 Frank 20
2 9/1/2012 John 20
Note that if two people have highest score for given day, it will print them both. For example:
INSERT INTO tbl1 VALUES ('John',10,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('John',20,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('John',5,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('Harry',20,to_date('20120901','YYYYMMDD'));
INSERT INTO tbl1 VALUES ('Frank',20,to_date('20121101','YYYYMMDD'));
select a.dt
, b.name
, a.score
FROM (SELECT dt
, MAX(score) score
FROM tbl1
GROUP BY dt) a
, (SELECT NAME
, dt
, MAX(score) score
FROM tbl1
GROUP BY name, dt) b
WHERE a.dt = b.dt
AND a.score = b.score
Output:
DT NAME SCORE
1 11/1/2012 Frank 20
2 9/1/2012 John 20
3 9/1/2012 Harry 20
I guess it is pretty simple
Select [Name], max([score]) as Score, [Date] from scoresTable
group by [Date], [Name]
Edited:
More accurate but a little complex
select o.[Name], i.[Date], i.Score from scoresTable o
inner join (select [Date], max(Score) as Score
from scoresTable group by [Date]) as i
on o.[Date] = i.[Date] and i.Score = o.Score
Even More, if your date field contains time too
select o.[Name], i.[Date], i.Score from scoresTable o
inner join (select convert(varchar, [Date], 101) as Date, max(Score) as Score
from scoresTable
group by convert(varchar, [Date], 101)) as i
on convert(varchar, o.[Date], 101) = i.[Date] and i.Score = o.Score