Help- Very Complex SQL query

  • Hi Guys,

    This ofcourse is my first post here today but I have spent whole bunch of time in working out one query (Without using loop/cursor) but still can't get it working.

    Below is a requirement.

    I have a table called Table1

    date1 date2

    1/1/2009 1/1/2009

    1/2/2009

    1/3/2009

    1/4/2009

    1/5/2009 1/5/2009

    1/6/2009

    1/7/2009

    1/8/2009

    1/9/2009

    1/10/2009 1/10/2009

    1/11/2009

    1/12/2009

    The desired output I need is

    Hi Guys,

    This ofcourse is my first post here today but I have spent whole bunch of time in working out one query (Without using loop/cursor) but still can't get it working.

    Below is a requirement.

    I have a table called Table1

    date1 date2

    1/1/2009 1/1/2009

    1/2/2009 1/1/2009

    1/3/2009 1/1/2009

    1/4/2009 1/1/2009

    1/5/2009 1/5/2009

    1/6/2009 1/5/2009

    1/7/2009 1/5/2009

    1/8/2009 1/5/2009

    1/9/2009 1/5/2009

    1/10/2009 1/10/2009

    1/11/2009 1/10/2009

    1/12/2009 1/10/2009

    Can anyone please help in giving me a clue?

    I don't want to user cursors/loop/CTE

    I just need to have this achieved with a complex sub-query.

  • To receive relatively quick assistance please post your table definition, sample data / desired output and what work you have attempted as per the directions in the first link in my signature block

    If everything seems to be going well, you have obviously overlooked something.

    Ron

    Please help us, help you -before posting a question please read[/url]
    Before posting a performance problem please read[/url]

  • hi there, below are the steps as per your instructions. Please see if you can help me out

    if OBJECT_ID('tempdb..#tmp_Dates') is not null

    drop table #tmp_Dates

    -- TABLE CREATION

    create table #tmp_Dates

    (

    value_date_intermediate datetime

    ,value_date_minus_1 datetime

    )

    -- VALUE INSERTION

    INSERT INTO #tmp_Dates VALUES ('1/1/2009','1/1/2009')

    INSERT INTO #tmp_Dates VALUES (NULL,'1/2/2009')

    INSERT INTO #tmp_Dates VALUES (NULL,'1/3/2009')

    INSERT INTO #tmp_Dates VALUES (NULL,'1/4/2009')

    INSERT INTO #tmp_Dates VALUES ('1/5/2009','1/5/2009')

    INSERT INTO #tmp_Dates VALUES (NULL,'1/6/2009')

    INSERT INTO #tmp_Dates VALUES (NULL,'1/7/2009')

    INSERT INTO #tmp_Dates VALUES ('1/8/2009','1/8/2009')

    INSERT INTO #tmp_Dates VALUES (NULL,'1/9/2009')

    INSERT INTO #tmp_Dates VALUES (NULL,'1/10/2009')

    INSERT INTO #tmp_Dates VALUES (NULL,'1/11/2009')

    INSERT INTO #tmp_Dates VALUES ('1/12/2009','1/12/2009')

    Desired Output

    #sampleData('1/1/2009','1/1/2009')

    #sampleData('1/1/2009','1/2/2009')

    #sampleData('1/1/2009','1/3/2009')

    #sampleData('1/1/2009','1/4/2009')

    #sampleData('1/5/2009','1/5/2009')

    #sampleData('1/5/2009''1/6/2009')

    #sampleData('1/5/2009','1/7/2009')

    #sampleData('1/8/2009','1/8/2009')

    #sampleData('1/8/2009','1/9/2009')

    #sampleData('1/8/2009','1/10/2009')

    #sampleData('1/8/2009','1/11/2009')

    #sampleData('1/12/2009','1/12/2009')

    Below is a query i have written but the problem is that it start updating from the second maximum value not the first.

    UPDATE t1

    SET t1.value_date_intermediate = t2.maxdate

    from #tmp_Dates t1

    INNER JOIN

    (

    SELECT MAX(value_date_minus_1) as maxdate, value_date_minus_1 FROM #tmp_Dates

    group by value_date_minus_1

    )t2

    on

    t2.maxdate >=t1.value_date_minus_1

  • create table #temp

    (

    date1 datetime null,

    date2 datetime null

    )

    insert into #temp (date1,date2)

    select '2009-01-01','2009-01-01' union all

    select '2009-01-02',null union all

    select '2009-01-03',null union all

    select '2009-01-04',null union all

    select '2009-01-05','2009-01-05' union all

    select '2009-01-06',null union all

    select '2009-01-07',null union all

    select '2009-01-08',null union all

    select '2009-01-09',null union all

    select '2009-01-10','2009-01-10' union all

    select '2009-01-11',null union all

    select '2009-01-12',null union all

    select '2009-01-13',null union all

    select '2009-01-14',null union all

    select '2009-01-15','2009-01-15' union all

    select '2009-01-16',null union all

    select '2009-01-17',null union all

    select '2009-01-18',null union all

    select '2009-01-19',null

    declare @datetime datetime

    set @datetime = null

    update #temp

    set @datetime = date2 = (case when date2 is not null then date2 else @datetime end)

    select * from #temp

  • Ohh buddy - that worked like a charm. I am such a fool not to think from basics.

  • Hey guys... Please read this article[/url] for all the rules in using this form of the update statement - they must be followed or you can get erroneous results!

    Wayne
    Microsoft Certified Master: SQL Server 2008
    Author - SQL Server T-SQL Recipes


    If you can't explain to another person how the code that you're copying from the internet works, then DON'T USE IT on a production system! After all, you will be the one supporting it!
    Links:
    For better assistance in answering your questions
    Performance Problems
    Common date/time routines
    Understanding and Using APPLY Part 1 & Part 2

  • WayneS (2/19/2010)


    Hey guys... Please read this article[/url] for all the rules in using this form of the update statement - they must be followed or you can get erroneous results!

    Wayne is absolutely right - you must make sure you follow the rules and fully understand this method.

    The example arun.sas posted happens to work in this case, but is absolutely not guaranteed to work in other situations.

    The posted code relies on rows being processed in a certain order. It just so happens that SQL Server returns rows from a heap in insertion order (as long as no data modification operations have ever occurred). This is a side-effect, not documented, supported, or recommended.

    You can mitigate the risks by following the advice in the link Wayne posted.

    Paul

  • DROP table #temp

    create table #temp

    (

    date1 datetime null,

    date2 datetime null

    )

    insert into #temp (date1,date2)

    select '2009-01-01','2009-01-01' union all

    select '2009-01-02',null union all

    select '2009-01-03',null union all

    select '2009-01-04',null union all

    select '2009-01-05','2009-01-05' union all

    select '2009-01-06',null union all

    select '2009-01-07',null union all

    select '2009-01-08',null union all

    select '2009-01-09',null union all

    select '2009-01-10','2009-01-10' union all

    select '2009-01-11',null union all

    select '2009-01-12',null union all

    select '2009-01-13',null union all

    select '2009-01-14',null union all

    select '2009-01-15','2009-01-15' union all

    select '2009-01-16',null union all

    select '2009-01-17',null union all

    select '2009-01-18',null union all

    select '2009-01-19',null

    UPDATE #temp SET date2 = d.date2

    FROM #temp t

    INNER JOIN(

    -- run this part to see what it does

    SELECT

    date1,

    date2 AS date2old,

    date2 = (SELECT MAX(date2) FROM #temp WHERE date2 <= t.date1)

    FROM #temp t

    -- /run this part to see what it does

    ) d ON d.date1 = t.date1

    SELECT * FROM #temp


    [font="Arial"]Low-hanging fruit picker and defender of the moggies[/font]

    For better assistance in answering your questions, please read this[/url].


    Understanding and using APPLY, (I)[/url] and (II)[/url] Paul White[/url]

    Hidden RBAR: Triangular Joins[/url] / The "Numbers" or "Tally" Table: What it is and how it replaces a loop[/url] Jeff Moden[/url]

  • Hi,

    nice move with inner join.

    But the situation always not with max date

    UPDATE t

    SET t.date2 = (SELECT MAX(date2) FROM #temp WHERE date2 <= t.date1)

    from #temp t

    However, you should see the article posted by Wayne or at least put the identity to make sure the correct sort order.

  • arun.sas (2/20/2010)


    Hi,

    nice move with inner join.

    But the situation always not with max date

    UPDATE t

    SET t.date2 = (SELECT MAX(date2) FROM #temp WHERE date2 <= t.date1)

    from #temp t

    However, you should see the article posted by Wayne or at least put the identity to make sure the correct sort order.

    The results exactly match the OP's requirements using either his/her sample data set or yours.

    No index or "sort order" is required for this simple query to operate correctly. The running totals update is dependant upon row order so it's best to assume that a clustered index over the desired "sort order" is essential in every case - and even then there are caveats particularly with Enterprise edition and partitioned tables. If in doubt, use a recursive CTE instead, it's surprisingly fast and has the advantage that an UPDATE isn't required.

    The OP has posted in the SS2K8 section - SS2K8 can perform tricks with correlated subqueries which substantially improve their performance over previous versions.


    [font="Arial"]Low-hanging fruit picker and defender of the moggies[/font]

    For better assistance in answering your questions, please read this[/url].


    Understanding and using APPLY, (I)[/url] and (II)[/url] Paul White[/url]

    Hidden RBAR: Triangular Joins[/url] / The "Numbers" or "Tally" Table: What it is and how it replaces a loop[/url] Jeff Moden[/url]

  • Here's a CTE solution to this problem - just the SELECT, but easy enough to use as the input for an UPDATE FROM:

    ;WITH NumberedSet AS (

    SELECT RowNum = ROW_NUMBER() OVER (ORDER BY date1), date1, date2

    FROM #temp),

    OutputSet AS (

    SELECT n.RowNum,

    n.date1,

    n.date2,

    CarryOver = date2

    FROM NumberedSet n

    WHERE RowNum = 1

    UNION ALL

    SELECT n.RowNum,

    n.date1,

    date2 = ISNULL(n.date2, o.CarryOver),

    CarryOver = ISNULL(n.date2, o.CarryOver)

    FROM OutputSet o

    INNER JOIN NumberedSet n ON n.RowNum = o.RowNum + 1)

    SELECT date1, date2

    FROM OutputSet

    It's quite a bit more complex than the correlated subquery or running totals solutions, but well investing some time on.


    [font="Arial"]Low-hanging fruit picker and defender of the moggies[/font]

    For better assistance in answering your questions, please read this[/url].


    Understanding and using APPLY, (I)[/url] and (II)[/url] Paul White[/url]

    Hidden RBAR: Triangular Joins[/url] / The "Numbers" or "Tally" Table: What it is and how it replaces a loop[/url] Jeff Moden[/url]

  • Hi,

    I know this, friend!

    The tips/advice made based on the OP query.

    I puzzling in some body say it have not guaranteed to work in other situations.

  • arun.sas (2/20/2010)


    However, you should see the article posted by Wayne or at least put the identity to make sure the correct sort order.

    Are you suggesting that a column with the IDENTITY property guarantees something about sort order?

    I certainly hope not, since that would be entirely wrong πŸ˜›

  • Hi,

    Certainly Paul,

    The situations are varying from the OP.

    For the OP issue, I felt its enough, it’s my point.

  • Hi Arun

    Follow the link to Jeff Moden's article in Wayne's post above. The article explains in great detail how to perform the quirky update and also identifies those situations where the method requires modification to work properly. There's a link in paragraph 3 to an article by Lynn Pettis which describes how he solved the problems observed when the quirky update is run against partitioned tables.

    The point is this: the quirky update is not guaranteed to work without at least a clustered index over the required processing order.


    [font="Arial"]Low-hanging fruit picker and defender of the moggies[/font]

    For better assistance in answering your questions, please read this[/url].


    Understanding and using APPLY, (I)[/url] and (II)[/url] Paul White[/url]

    Hidden RBAR: Triangular Joins[/url] / The "Numbers" or "Tally" Table: What it is and how it replaces a loop[/url] Jeff Moden[/url]

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

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