Time, Count(Hits)

  • I have table with LoginDateTime (i.e. 01-Jan-2007 10:10 PM) and several other columns. I have to make report that may show results like:

    hours wise Login hits.

    Hit timeHits
    1 to 210
    2 to 325
    3 to 437
    4 to 5258
    5 to 613
    6 to 712
    7 to 88
    8 to 945
    9 to 1033
    10 to 1165
    11 to 1258
    12 to 1384
    13 to 1445
    14 to 1565
    15 to 1687
    16 to 176
    17 to 1866
    18 to 19158
    19 to 2065
    20 to 2185
    21 to 2275
    22 to 2396
    23 to 2422

    how to do :

    I want dynamic sort aswell.

    Declare @dt datetime

    set @dt = '01/01/2007'

    select datepart(hour, LoginDateTime ), count(*) from LoginTrack

    group by datepart(hour, LoginDateTime)

    order by 1

    but its not showing if there is no any hit in specific time, it should print all time slots from 1 to 24 hrs like above.

    Plz help

     

    Shamshad Ali.

     

  • -- Prepare sample data

    DECLARE

    @LoginTrack TABLE (LoginDateTime DATETIME)

    INSERT

    @LoginTrack (LoginDateTime)

    SELECT

    TOP 10000

    DATEADD(SECOND, ABS(CHECKSUM(NEWID())), 0)

    FROM

    syscolumns as s1

    CROSS

    JOIN syscolumns as s2

    -- Show the expected output

    SELECT

    CONVERT(VARCHAR, v.Number) + ' to ' + CONVERT(VARCHAR, v.Number + 1) AS [Hit time],

    COUNT(*) AS Hits

    FROM

    master..spt_values AS v

    LEFT

    JOIN @LoginTrack AS lt ON DATEPART(HOUR, lt.LoginDateTime) BETWEEN v.Number AND v.Number + 1

    WHERE

    v.Type = 'p'

    AND v.Number BETWEEN 0 AND 23

    GROUP

    BY v.Number

    ORDER

    BY v.Number


    N 56°04'39.16"
    E 12°55'05.25"

  • Thanks Peter, Your help is appreciated. Further more there are TOP 1000 rows. For real scenario If i have no hit during 7 to 9 it should return me 0 againt 7 to 8 and 8 to 9. But that is no doing so.

     Also if i put TOP 5, it shows 1 hit per Hit Time that is not a valid outcome. Plz. help

    DECLARE

    @LoginTrack TABLE (LoginDateTime DATETIME)

    INSERT

    @LoginTrack (LoginDateTime)

    SELECT

    TOP 5

    DATEADD

    (SECOND, ABS(CHECKSUM(NEWID())), 0)

    FROM

    syscolumns as s1

    CROSS

    JOIN syscolumns as s2

    -- select * from @LoginTrack

    -- Show the expected output

    SELECT

    CONVERT(VARCHAR, v.Number) + ' to ' + CONVERT(VARCHAR, v.Number + 1) AS [Hit time],

    COUNT

    (*) AS Hits

    FROM

    master..spt_values AS v

    LEFT

    JOIN @LoginTrack AS lt ON DATEPART(HOUR, lt.LoginDateTime) BETWEEN v.Number AND v.Number + 1

    WHERE

    v.Type = 'p'

    AND

    v.Number BETWEEN 0 AND 23

    GROUP

    BY v.Number

    ORDER

    BY v.Number

    LoginDateTime
    1902-04-11 05:30:45.000
    1903-10-07 07:42:37.000
    1909-02-28 19:29:41.000
    1925-07-05 23:35:29.000
    1926-02-13 03:37:30.000

    Hit timeHits
    0 to 11
    1 to 21
    2 to 31
    3 to 41
    4 to 51
    5 to 61
    6 to 71
    7 to 81
    8 to 91
    9 to 101
    10 to 111
    11 to 121
    12 to 131
    13 to 141
    14 to 151
    15 to 161
    16 to 171
    17 to 181
    18 to 191
    19 to 201
    20 to 211
    21 to 221
    22 to 231
    23 to 241

     Plz. check and help.

    Shamshad Ali.

  • SELECT CONVERT(VARCHAR, v.Number) + ' to ' + CONVERT(VARCHAR, v.Number + 1) AS [Hit time],

    (SELECT COUNT(*) FROM @LoginTrack Z WHERE DATEPART(hour, Z.LoginDateTime) = V.Number) AS Hits

    FROM master..spt_values AS v

    WHERE v.Type = 'P'

    AND v.Number BETWEEN 0 AND 23

  • Great !!!

     

    Thanks you all for ur time and help.

    Shamshad Ali.

  • CREATE TABLE #LoginTrack (RowID INT IDENTITY(1, 1) PRIMARY KEY, LoginDateTime DATETIME)

     

    INSERT      #LoginTrack

                (

                            LoginDateTime

                )

    SELECT      TOP 100000

                DATEADD(SECOND, ABS(CHECKSUM(NEWID())), 0)

    FROM        syscolumns as s1

    CROSS JOIN  syscolumns as s2

     

    DECLARE     @dt DATETIME

     

    -- Peso

    DBCC FREEPROCCACHE

    DBCC DROPCLEANBUFFERS

     

    set @dt = current_Timestamp

     

    SELECT      CONVERT(VARCHAR, v.Number) + ' to ' + CONVERT(VARCHAR, v.Number + 1) AS [Hit time],

                COUNT(lt.LoginDateTime) AS Hits

    FROM        master..spt_values AS v

    LEFT JOIN   #LoginTrack AS lt ON DATEPART(HOUR, lt.LoginDateTime) = v.Number

    WHERE       v.Type = 'p'

                AND v.Number BETWEEN 0 AND 23

    GROUP BY    v.Number

    ORDER BY    v.Number

     

    select datediff(ms, @dt, current_timestamp)

     

    -- Koji

    DBCC FREEPROCCACHE

    DBCC DROPCLEANBUFFERS

     

    set @dt = current_Timestamp

     

    SELECT      CONVERT(VARCHAR, v.Number) + ' to ' + CONVERT(VARCHAR, v.Number + 1) AS [Hit time],

                (SELECT COUNT(*) FROM #LoginTrack Z WHERE DATEPART(hour, Z.LoginDateTime) = V.Number) AS Hits

    FROM        master..spt_values AS v

    WHERE       v.Type = 'P'

                AND v.Number BETWEEN 0 AND 23

    ORDER BY    v.Number

     

    select datediff(ms, @dt, current_timestamp)

     


    Also the reads are down from 6581 to 269, a speed factor of 24 times faster.

    And the time is down from 546 ms to 63 ms, a speed factor of 8 times faster.

     

     


    N 56°04'39.16"
    E 12°55'05.25"

  • Peso,

    I have been reading many of you and a few others's excellent solutions.

    I know join is much more efficient.

    I have learned that from you and Jeff M and a few others.

    However, I feel it is not that easy to understand for non-experienced members.

    It is not a contest and he is not asking to optimize.

    If he is smart enough to understand your version,

    he should have been able to come up with mine from your original post, don't you think?

    Anyways, I'm always looking forward to see your posts.

    Koji

  • I believe that if OP is new (non-experienced) to SQL Server, he or she is better of learning the proper [ansi join] way directly, instead of learning them CORRELATED SUBQUERIES, if they can be avoided.

     


    N 56°04'39.16"
    E 12°55'05.25"

  • wat if the sql user has no permit to master.. permit?

    Furthermore, I require percentage per hr. how to do this?

    No.Hit DurationPercentHits
    100:00 to 01:00 6.67% 1
    201:00 to 02:00 0% 0
    302:00 to 03:00 0% 0
    403:00 to 04:00 0% 0
    504:00 to 05:00 6.67% 1
    605:00 to 06:00 0% 0
    706:00 to 07:00 0% 0
    807:00 to 08:00 0% 0
    908:00 to 09:00 6.67% 1
    1009:00 to 10:00 6.67% 1
    1110:00 to 11:00 13.33% 2
    1211:00 to 12:00 20% 3
    1312:00 to 13:00 0% 0
    1413:00 to 14:00 0% 0
    1514:00 to 15:00 13.33% 2
    1615:00 to 16:00 6.67% 1
    1716:00 to 17:00 6.67% 1
    1817:00 to 18:00 0% 0
    1918:00 to 19:00 0% 0
    2019:00 to 20:00 0% 0
    2120:00 to 21:00 0% 0
    2221:00 to 22:00 0% 0
    2322:00 to 23:00 6.67% 1
    2423:00 to 24:00 6.67% 1
    TOTAL:100%15

    Shamshad Ali.

  • SELECT      v.Number + 1 AS Hit,

                CONVERT(CHAR(5), DATEADD(HOUR, v.Number, 0), 108) + ' to ' + CONVERT(CHAR(5), DATEADD(HOUR, v.Number + 1, 0), 108) AS [Hit Duration],

                CONVERT(DECIMAL(5, 2), 100.0 * COUNT(lt.LoginDateTime) / t.h) AS [Percent],

                COUNT(lt.LoginDateTime) AS Hits

    FROM        (

                            SELECT 0 AS Number UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL

                             SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL

                             SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL

                             SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15 UNION ALL

                             SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19 UNION ALL

                             SELECT 22 UNION ALL SELECT 21 UNION ALL SELECT 22 UNION ALL SELECT 23

                ) AS v

    CROSS JOIN  (

                            SELECT COUNT(*) AS h FROM LoginTrack

                ) AS t

    LEFT JOIN   LoginTrack AS lt ON DATEPART(HOUR, lt.LoginDateTime) = v.Number

    GROUP BY    v.Number,

                t.h

    ORDER BY    v.Number

     


    N 56°04'39.16"
    E 12°55'05.25"

  • Peter, once again thanks for your support and help.

    I have following query and results, that are showing me actual data with date/ time:

    Declare

     @todate datetime, 

     @fromdate datetime, 

     @channelid numeric(9)

     

    set @todate = '01/01/2007'

    set @fromdate = '01/01/2007'

    select LoginDateTime from LoginTrack

    where convert (varchar, LoginDateTime,101) between @fromdate and @todate

    order by LoginDateTime

     

    No.Login_datetime
    12007-01-01 04:00:00.000
    22007-01-01 08:00:00.000
    32007-01-01 09:00:00.000
    42007-01-01 10:26:18.503
    52007-01-01 11:00:00.000
    62007-01-01 11:00:00.000
    72007-01-01 11:00:00.000
    82007-01-01 14:00:00.000
    92007-01-01 14:52:27.817
    102007-01-01 16:00:00.000
    112007-01-01 22:00:00.000
    122007-01-01 23:00:00.000

    now when I apply your query to get desired results its Total count (that should be 12) is now 13. Is there any thing wrong with my checking query above to find actual data for a day (01/01/07)?

    here is my modified query and its output.

    Declare

     @todate datetime, 

     @fromdate datetime, 

     @channelid numeric(9)

     

    set @todate = '01/01/2007'

    set @fromdate = '01/01/2007'

     

     

    SELECT      v.Number + 1 AS Hit,

                CONVERT(CHAR(5), DATEADD(HOUR, v.Number, 0), 108) + ' to ' + CONVERT(CHAR(5), DATEADD(HOUR, v.Number + 1, 0), 108) AS [Hit Duration],

                CONVERT(DECIMAL(5, 2), 100.0 * COUNT(lt.LoginDateTime) / t.h) AS [Percent],

                COUNT(lt.LoginDateTime) AS Hits

    FROM        (

                            SELECT 0 AS Number UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL

                             SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL

                             SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL

                             SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15 UNION ALL

                             SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19 UNION ALL

                             SELECT 22 UNION ALL SELECT 21 UNION ALL SELECT 22 UNION ALL SELECT 23

                ) AS v

    CROSS JOIN  (

                            SELECT COUNT(*) AS h FROM LoginTrack

    where convert (varchar, LoginDateTime,101) between @fromdate and @todate

     

                ) AS t

    LEFT JOIN   LoginTrack AS lt ON DATEPART(HOUR, lt.LoginDateTime) = v.Number

    where convert (varchar, lt.LoginDateTime,101) between @fromdate and @todate

    GROUP BY    v.Number,

                t.h

    ORDER BY    v.Number

    <TD class=xl26 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" align=right x:num x:fmla="=SUM(D210)">13

    HitHit durationPercentHits
    504:00 to 05:008.331
    908:00 to 09:008.331
    1009:00 to 10:008.331
    1110:00 to 11:008.331
    1211:00 to 12:00253
    1514:00 to 15:0016.672
    1716:00 to 17:008.331
    2322:00 to 23:0016.672
    2423:00 to 00:008.331
     Total 

    Plz. see if my first query above is wrong? Is this wrong approach? Aslo I can't get all 24 rows in output above.

    where convert (varchar, LoginDateTime,101) between @fromdate and @todate

    May between work with above or NOT? users can put any date range but for checking purpose i just input from and to date as '01/01/07' to find actual data in table for a day and get correct outcome.

     

    Shamshad Ali.

  • DECLARE     @ToDate DATETIME,

                @FromDate DATETIME,

                @ChannelID NUMERIC(9)

     

    SELECT      @ToDate = '01/01/2007',

                @FromDate = '01/01/2007'

     

    SELECT      v.Number + 1 AS Hit,

                CONVERT(CHAR(5), DATEADD(HOUR, v.Number, 0), 108) + ' to ' + CONVERT(CHAR(5), DATEADD(HOUR, v.Number + 1, 0), 108) AS [Hit Duration],

                CONVERT(DECIMAL(5, 2), 100.0 * COUNT(lt.LoginDateTime) / t.h) AS [Percent],

                COUNT(lt.LoginDateTime) AS Hits

    FROM        (

                             SELECT 0 AS Number UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL

                            SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL

                            SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL

                            SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15 UNION ALL

                            SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19 UNION ALL

                            SELECT 22 UNION ALL SELECT 21 UNION ALL SELECT 22 UNION ALL SELECT 23

                ) AS v

    CROSS JOIN  (

                            SELECT      COUNT(*) AS h

                            FROM        LoginTrack

                            WHERE       LoginDateTime >= @FromDate

                                         AND LoginDateTime < DATEADD(DAY, 1, @ToDate)

                ) AS t

    LEFT JOIN   LoginTrack AS lt ON DATEPART(HOUR, lt.LoginDateTime) = v.Number

                            AND lt.LoginDateTime >= @FromDate

                            AND lt.LoginDateTime < DATEADD(DAY, 1, @ToDate)

    GROUP BY    v.Number,

                t.h

    ORDER BY    v.Number

     

     


    N 56°04'39.16"
    E 12°55'05.25"

  • BTW, are you using SQL Server 2000 or SQL Server 2005?

     


    N 56°04'39.16"
    E 12°55'05.25"

  • SQL Server 2000 SP4

  • Again, Again, in my second last reply i checked actual rows in table were 12 and the count is giving me 13 rows with your given query output. that should return 12 Hits if we count result.

    Shamshad Ali.

Viewing 15 posts - 1 through 15 (of 17 total)

You must be logged in to reply to this topic. Login to reply