Top 1 or Max??

  • What you be the best syntax?

    I need to get from a table, from a particular set of rows, the one with the max date

    Syntax 1:

    SELECT TOP 1 * FROM MyTable

    WHERE MyForeignIdColumn = 400

    ORDER BY MyDateColumn DESC

    Syntax 2:

    SELECT * FROM MyTable

    WHERE MyDateColumn = (SELECT max(MyDateColumn) from MyTable WHERE MyForeignIdColumn = 400)

    thank you

    Martin

  • It depends on whether or not you believe in the myth of portable code. TOP is an SQL Server manifestation.

    Other than that, "best", in my book, is the one that does all of the following...

    1. Works correctly

    2. Is the fastest

    3. Uses the least amount of resources (memory, drive, cpu... in that order for me).

    Now, you're asking a question as to which is best. Lemme ask you a question... who are you going to believe? Answer should be, "No One". "A Developer must not guess... a Developer must KNOW." Set up a test and discover the correct answer.

    For the record, I don't believe in the myth. 😉

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • I agree with Jeff, portable code is a myth.

    For the type of query you're running, let me say one thing, look at the execution plan for each query. I wouldn't be at all surprised if you saw the same operation occurring for both queries. In this instance, that'll give you your answer.

    "The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood"
    - Theodore Roosevelt

    Author of:
    SQL Server Execution Plans
    SQL Server Query Performance Tuning

  • If there are multiple rows with the same date-time in the MyDateColumn, the first query will only give you one of them, but the second query will give you all of them. That needs to be taken into account when you decide which is "best".

    The second query will also return rows with the wrong MyForeignID if they happen to have the same MyDate.

    Tested this:

    if object_id(N'tempdb..#T') is not null

    drop table #T

    create table #T (

    ID int identity primary key,

    MyDate datetime,

    MyForeignID int);

    insert into #T (MyDate, MyForeignID)

    select checksum(newid())%1000, checksum(newid())%1000

    from dbo.Numbers

    where number <= 100000;

    create index IDX_T on #T(MyForeignID, MyDate);

    set statistics io on;

    set statistics time on;

    select top 1 *

    from #T

    where MyForeignID = 400

    order by MyDate desc;

    select *

    from #T

    where MyForeignID = 400

    and MyDate =

    (select max(MyDate)

    from #T

    where MyForeignID = 400);

    Both ended up with 1 millisecond execution time, and with identical execution plans.

    - Gus "GSquared", RSVP, OODA, MAP, NMVP, FAQ, SAT, SQL, DNA, RNA, UOI, IOU, AM, PM, AD, BC, BCE, USA, UN, CF, ROFL, LOL, ETC
    Property of The Thread

    "Nobody knows the age of the human race, but everyone agrees it's old enough to know better." - Anon

  • GSquared (2/2/2009)


    If there are multiple rows with the same date-time in the MyDateColumn, the first query will only give you one of them, but the second query will give you all of them. That needs to be taken into account when you decide which is "best".

    The second query will also return rows with the wrong MyForeignID if they happen to have the same MyDate.

    Heh... long winded version of...

    1. Works correctly

    😛

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • [font="Verdana"]Is the MyDateColumn unique? Because if it's not, the second form could return more than one row.

    Ooops, really should read all of the replies before posting. Someone already pointed that out.[/font]

  • Bruce W Cassidy (2/2/2009)


    [font="Verdana"]Is the MyDateColumn unique? Because if it's not, the second form could return more than one row.

    Ooops, really should read all of the replies before posting. Someone already pointed that out.[/font]

    S'ok... just confirms what the others said.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Grant Fritchey (2/2/2009)


    I agree with Jeff, portable code is a myth.

    Oh yeah??!! Well, what if I code on a laptop, huh? Huh?

    Thought so.

    ---------------------------------------------------------
    How best to post your question[/url]
    How to post performance problems[/url]
    Tally Table:What it is and how it replaces a loop[/url]

    "stewsterl 80804 (10/16/2009)I guess when you stop and try to understand the solution provided you not only learn, but save yourself some headaches when you need to make any slight changes."

  • dubem1 (1/31/2009)


    What you be the best syntax?

    I need to get from a table, from a particular set of rows, the one with the max date

    Syntax 1:

    SELECT TOP 1 * FROM MyTable

    WHERE MyForeignIdColumn = 400

    ORDER BY MyDateColumn DESC

    Syntax 2:

    SELECT * FROM MyTable

    WHERE MyDateColumn = (SELECT max(MyDateColumn) from MyTable WHERE MyForeignIdColumn = 400)

    thank you

    Martin

    Go with syntax 1.

    Syntax 2 is logically incorrect for your requirements. It would not ensure that the row returned is MyForeignIdColumn = 400, and it would not ensure that it returns only one row.

  • Code i used was CTE

    WITH CTE AS (

    SELECT EMPL_ID, effective_dt, ORG,

    ROW_NUMBER() OVER(PARTITION BY EMPL_ID ORDER BY effective_dt DESC) AS rn

    FROM TABLE)

    INSERT INTO TEMPTABLE

    SELECT EMPL_ID, effective_dt, ORG

    FROM CTE

    WHERE rn=1 AND EMPL_ID LIKE 'A156'

  • jcrawf02 (2/3/2009)


    Grant Fritchey (2/2/2009)


    I agree with Jeff, portable code is a myth.

    Oh yeah??!! Well, what if I code on a laptop, huh? Huh?

    Thought so.

    😀

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

Viewing 11 posts - 1 through 10 (of 10 total)

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