Home > front end >  SQL Substitute value based on same field
SQL Substitute value based on same field

Time:07-16

I am trying to evaluate how long a user is potentially online for.

Below is the data structure I am working with.

Name Date Time Event
John 2022-01-01 10:00 Log-On
John 2022-01-01 11:00 Log-Off
John 2022-01-02 09:00 Log-Off
John 2022-01-03 15:00 Log-On

I am using the following logic:

  • When the Log-On time is not provided, use the Log-Off time.
  • When the Log-Off time is not provided, use the Log-On time.
  • I am taking the MIN LogOn time for a particular day.
  • I am taking the MAX LogOff time for a particular day.

Below is the expected Outcome:

ID Name Date MinLogOnTime MaxLogOffTime TimeDifferenceHr ( Max - Min Time)
1 John 2022-01-01 10:00 11:00 1
2 John 2022-01-02 09:00 09:00 0
3 John 2022-01-03 15:00 15:00 0

Below is a query that I having been trying, but with no luck yet:

SELECT      [Name]
            ,[Date]
            ,ISNULL(LogOn, MIN(CASE WHEN [Event] IN ('Log-Off') THEN [Time] ELSE NULL END)) AS MinLogOnTime
            ,ISNULL(LogOff, MAX(CASE WHEN [Event] IN ('Log-On') THEN [Time] ELSE NULL END)) AS MaxLogOffTime
            ,DATEDIFF(HH, ISNULL(LogOff, MAX(CASE WHEN [Event] IN ('Log-Off') THEN [Time] ELSE NULL END)), ISNULL(LogOn, MIN(CASE WHEN [Event] IN ('Log-On') THEN [Time] ELSE NULL END)) AS 'TimeDifferenceHr ( Max - Min Time)'

FROM        (
            SELECT          [Name]
                            ,[Date]
                            ,[Event]
                            ,MIN(CASE WHEN [Event] IN ('Log-On') THEN [Time] ELSE NULL END) AS LogOn 
                            ,MAX(CASE WHEN [Event] IN ('Log-Off') THEN [Time] ELSE NULL END) AS LogOff 
            GROUP BY        [Name], [Date], [Event]
            ) x
GROUP BY    [Name], [Date]
ORDER BY    [Name], [Date]

I would really appreciate any assistance with this.

CodePudding user response:

based on the comments, it seems you just need some conditional aggregation. As you might not have a On/Off for each day, then you need to get the MIN/MAX for both event types, and then you can use ISNULL (or COALESCE):

WITH CTE AS(
    SELECT Name,
           [Date],
           MIN(CASE Event WHEN 'Event' THEN [Time] END) AS MinLogOnTime,
           MAX(CASE Event WHEN 'Event' THEN [Time] END) AS MaxLogOnTime,
           MIN(CASE Event WHEN 'Event' THEN [Time] END) AS MinLogOffTime,
           MAX(CASE Event WHEN 'Event' THEN [Time] END) AS MaxLogOffTime
    FROM dbo.YourTable
    GROUP BY Name,
             [Date])
SELECT Name,
       Date,
       ISNULL(MinLogOnTime,MinLogOffTime) AS MinLogOnTime,
       ISNULL(MaxLogOffTime,MaxLogOnTime) AS MaxLogOffTime,
       DATEDIFF(HOUR,ISNULL(MaxLogOffTime,MaxLogOnTime),ISNULL(MaxLogOffTime,MaxLogOnTime)) AS TimeDifference
FROM CTE;
  • Related