Is there a more efficient way to write this query?

  • I have a table in the following format

    IF OBJECT_ID(N'tempdb..#DriveInfo') IS NULL

    BEGIN

    CREATE TABLE #DriveInfo(

    [pkDriveRecordID] [int] NOT NULL,

    [fkServerID] [int] NOT NULL,

    [DriveLetter] [char](1) NOT NULL,

    [CapacityMB] [bigint] NOT NULL,

    [UsedSpaceMB] [bigint] NOT NULL,

    [FreeSpaceMB] [bigint] NOT NULL,

    [FreeSpacePercent] [tinyint] NOT NULL,

    [ClusterSizeKB] [smallint] NULL,

    [FileFragmentationPercent] [tinyint] NULL,

    [TotalFragmentationPercent] [tinyint] NULL,

    [FreeSpaceFragmentationPercent] [tinyint] NULL,

    [FileFragmentCount] [bigint] NULL,

    [ExcessFolderFragmentCount] [bigint] NULL,

    [EntryDateTime] [datetime] NOT NULL

    )

    END

    GO

    INSERT INTO #DriveInfo

    SELECT 1, 3, N'C', 14324, 11126, 3198, 22, 4096, 43, 22, 1, 63988, 2150, CAST(0x00009D1401149A41 AS DateTime)

    UNION

    SELECT 2, 4, N'C', 14324, 11652, 2672, 19, 4096, 48, 25, 2, 56794, 1798, CAST(0x00009D1401149A41 AS DateTime)

    I need to be able to retrieve the most recent record fom this table for a given pkServerID and DriveLetter and return the following table format

    IF OBJECT_ID(N'tempdb..#DriveSpace') IS NULL

    BEGIN

    Create Table #DriveSpace(

    Category varchar(20),

    SizeInMB bigint

    )

    END

    GO

    INSERT INTO #DriveSpace

    SELECT 'FreeSpace', 3198

    UNION

    SELECT 'UsedSpace', 11126

    The sql I'm currently using is as follows

    -- Used for comparison between desired format and query

    SELECT * FROM #DriveSpace

    SELECT 'FreeSpace' Measurement, D.FreeSpaceMB SizeInMB

    FROM #DriveInfo D

    WHERE D.fkServerID = 3 AND D.DriveLetter = 'C' AND D.EntryDateTime =

    (

    SELECT Max(EntryDateTime)

    FROM #DriveInfo

    WHERE D.fkServerID = fkServerID AND D.DriveLetter = DriveLetter

    )

    UNION

    SELECT 'UsedSpace' Measurement, D.UsedSpaceMB SizeInMB

    FROM #DriveInfo D

    WHERE D.fkServerID = 3 AND D.DriveLetter = 'C' AND D.EntryDateTime =

    (

    SELECT Max(EntryDateTime)

    FROM #DriveInfo

    WHERE D.fkServerID = fkServerID AND D.DriveLetter = DriveLetter

    )

    Although the code above works, I am wondering if there is perhaps a more efficient query I could use. This table will end up quite large over time and I would rather be efficient now than have to come back to it later once it starts to slow down.

    Many Thanks,

    Paul

  • I am not sure what you are trying to do. If you want the latest information for each drive then try something like:

    SELECT fkServerID, DriveLetter, FreeSpaceMB, UsedSpaceMB

    FROM

    (

    SELECT fkServerID, DriveLetter, FreeSpaceMB, UsedSpaceMB

    ,ROW_NUMBER() OVER (PARTITION BY fkServerID, DriveLetter ORDER BY EntryDateTime DESC) AS RowNum

    FROM #DriveInfo

    ) D

    WHERE RowNum = 1

  • On looking at it again, maybe the following:

    SELECT

    CASE

    WHEN N.N = 1

    THEN 'FreeSpace'

    ELSE 'UsedSpace'

    END AS Measurement

    ,CASE

    WHEN N.N = 1

    THEN FreeSpaceMB

    ELSE UsedSpaceMB

    END AS SizeInMB

    FROM

    (

    SELECT FreeSpaceMB, UsedSpaceMB

    ,ROW_NUMBER() OVER (ORDER BY EntryDateTime DESC) AS RowNum

    FROM #DriveInfo

    WHERE fkServerID = 3 AND DriveLetter = 'C'

    ) D

    CROSS JOIN

    (

    SELECT 1 UNION ALL

    SELECT 2

    ) N(N)

    WHERE RowNum = 1

  • The second query is perfect. Thank you very much!

    Just goes to show how much I still need to learn about T-SQL 🙂

    Cheers,

    Paul.

  • Even 'perfection' may be improved, perhaps...

    WITH Data

    AS (

    -- This does the hard work of

    -- getting the data

    SELECT TOP (1)

    UsedSpaceMB,

    FreeSpaceMB

    FROM #DriveInfo

    WHERE fkServerID = 3

    AND DriveLetter = 'C'

    ORDER BY

    EntryDateTime DESC

    )

    -- This just turns the columns into rows

    SELECT Result.Measurement, Result.SizeInMB

    FROM Data

    UNPIVOT (

    SizeInMB

    FOR Measurement IN

    ([UsedSpaceMB], [FreeSpaceMB])

    ) AS Result;

    🙂 😎 🙂

    Paul

  • SELECT TOP (1) WITH TIES add to code of Paul White

    Because can be more than one record

    I Have Nine Lives You Have One Only
    THINK!

  • handkot (2/20/2010)


    SELECT TOP (1) WITH TIES add to code of Paul White

    Because can be more than one record

    I doubt you'd want more than one record returned in this scenario - and the test data supplied did not include any duplicates.

    That said, it is generally good practice to include a tie-breaker column when looking for one result, so perhaps a better solution would be to change the ORDER BY to EntryDateTime DESC, pkDriveRecordID DESC.

    Paul

  • Thanks for all of your help guys. It's much appreciated. 🙂

Viewing 8 posts - 1 through 7 (of 7 total)

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