Home > Mobile >  How to Group by a column irrespective of other column and return all corresponding rows?
How to Group by a column irrespective of other column and return all corresponding rows?

Time:05-20

I am having staff's movement data in table AttendanceReg like:

EmpId InPlace InTime OutTime
001 Plc01 10AM 11AM
002 Plc01 10AM 11AM
001 Plc02 11AM 12PM
002 Plc02 11AM 07PM
001 Plc01 12PM 06PM
003 Plc01 10AM 08PM

I want a report of Employees with their 1st In and last out with it's place. (should depends In and Out time, not the place)

when I tried aggregate function and group by, it returned:

Alter PROCEDURE UDP_AttReport @SelectDt Date
AS
select EmpID as ID,max(InPlace) as InPlace,min(InTime) as InTime Into #AttIN from AttendanceReg where cast(InTime as Date) = cast(@SelectDt as date) group by EmpID order by InTime desc 
select EmpID as ID, max(InPlace)as OutPlace,max(OutTime) as OutTime Into #AttOut from AttendanceReg where cast(InTime as Date) = cast(@SelectDt as date) group by EmpID order by OutTime desc 

SELECT #AttIN.ID,InPlace,InTime,OutPlace,OutTime Into #AttRep FROM #AttIN
RIGHT JOIN #AttOut
ON #AttIN.ID = #AttOut.ID
select ID,InPlace,InTime,OutPlace,OutTime from #AttRep Order by InTime asc

drop table #AttIN
drop table #AttOut
drop table #AttRep

Go
EmpId InPlace InTime OutPlace OutTime
001 Plc02 10AM Plc02 06PM
002 Plc02 11AM Plc02 07PM
003 Plc01 10AM Plc01 08AM

but what I expect is

EmpId InPlace InTime OutPlace OutTime
001 Plc01 10AM Plc01 06PM
002 Plc01 10AM Plc02 07PM
003 Plc01 10AM Plc01 08PM

I can understand the problem is with using Max(InPlace) (I learnt it somewhere to trick SQL to return the column without grouping by that column).

Thanks.

CodePudding user response:

Try this :

Select  a.EmpId, 
        a.InPlace, 
        a.InTime,
        b.Inplace as Outplace , 
        b.OutTime
From
    (Select EmpId, InPlace, InTime, ROW_NUMBER() over(partition by EmpId order by InTime) rn From test) a
inner join 
    (Select EmpId, InPlace, OutTime, ROW_NUMBER() over(partition by EmpId order by OutTime desc) rn From test) b
on 
    a.EmpId = b.EmpId
Where 
   a.rn = 1 
   and b.rn = 1

Output enter image description here

CodePudding user response:

use window function row_number() to find the first and last In or Out by EmpId

with cte as
(
    select *, 
           rn = row_number() over (partition by EmpId order by InTime),
           rc = count(*) over (partition by EmpId)
    from   AttendanceReg
)
select EmpId, 
       InPlace  = max(case when rn = 1 then InPlace end),
       InTime   = max(case when rn = 1 then InTime end),
       OutPlace = max(case when rn = rn then InPlace end),
       OutTime  = max(case when rn = rn then OutTime end)
from   cte
group by EmpId

Is there an error on the OutTime for 003? it is supposed to be 08PM?

  • Related