Help with the query

  • Hi all experts,

    I am sorry to post the problem of the same type , but i am not able to logically interpret how to traverse through the queries πŸ™

    Please see this code snippet under which i am trying to solve my problem , if possible pls help :crying:

    /*

    I want to traverse through the loop and find the event before HardDrink.

    */

    CREATE TABLE #TEMP (UserName varchar(20),Drink varchar(20),Value int,CreatedDate date)

    INSERT INTO #TEMP VALUES ('ABC','Coke',100,'2014-01-12') --Starts with coke or fanta (1st Cycle)

    INSERT INTO #TEMP VALUES ('ABC','Fanta',50,'2014-01-13')

    INSERT INTO #TEMP VALUES ('ABC','Pepsi',50,'2014-01-14')

    INSERT INTO #TEMP VALUES ('ABC','HardDrink',75,'2014-01-18') --ends with HardDrink

    INSERT INTO #TEMP VALUES ('ABC','Fanta',36,'2014-01-20') --Starts with Fanta (2nd Cycle)

    INSERT INTO #TEMP VALUES ('ABC','XXX',45,'2014-01-28')

    INSERT INTO #TEMP VALUES ('ABC','XXX',75,'2014-02-04')

    INSERT INTO #TEMP VALUES ('ABC','XXX',96,'2014-02-06')

    INSERT INTO #TEMP VALUES ('ABC','HardDrink',12,'2014-02-10') --ends with HardDrink

    INSERT INTO #TEMP VALUES ('ABC','Fanta',93,'2014-02-22') --Starts with Fanta (3rd Cycle)

    INSERT INTO #TEMP VALUES ('ABC','XXX',101,'2014-02-22')

    INSERT INTO #TEMP VALUES ('ABC','Pepsi',150,'2014-02-23')

    INSERT INTO #TEMP VALUES ('ABC','Pepsi',510,'2014-02-24')

    INSERT INTO #TEMP VALUES ('ABC','HardDrink',175,'2014-02-25') --end with HardDrink

    INSERT INTO #TEMP VALUES ('ABC','Fanta',136,'2014-02-26') --Starts with Fanta (4th Cycle)

    INSERT INTO #TEMP VALUES ('ABC','XXX',145,'2014-02-27')

    INSERT INTO #TEMP VALUES ('ABC','XXX',175,'2014-02-28')

    INSERT INTO #TEMP VALUES ('ABC','XXX',196,'2014-03-01')

    INSERT INTO #TEMP VALUES ('ABC','XXX',112,'2014-03-02')

    INSERT INTO #TEMP VALUES ('ABC','XXX',193,'2014-03-03')

    /*If harddrink present then the drink above it,

    for the last cycle , hardrink may or may not be present so if hardrink present then take the take the drink before it

    else the last drink.

    Output:

    UserNameDrinkValue

    ABCpepsi50

    ABCxxx96

    ABCpepsi510

    ABCxxx193

    */

  • JackTimber (9/4/2014)


    Hi all experts,

    I am sorry to post the problem of the same type , but i am not able to logically interpret how to traverse through the queries πŸ™

    Please see this code snippet under which i am trying to solve my problem , if possible pls help :crying:

    I've always called this kind of problem a "data smudge". Essentially, you want to smudge the data together :hehe:

    Try: -

    SELECT ad.UserName, ad.Drink, ad.Value, ad.CreatedDate

    FROM (

    SELECT UserName, Drink, Value, CreatedDate,

    MAX(CreatedDate) OVER ( ) AS MaxDate

    FROM #TEMP

    ) a

    CROSS APPLY (

    SELECT TOP 1

    b.UserName, b.Drink, b.Value, b.CreatedDate

    FROM #TEMP b

    WHERE (

    a.MaxDate = a.CreatedDate

    AND a.Drink <> 'HardDrink'

    AND a.CreatedDate = b.CreatedDate

    )

    OR (

    a.Drink = 'HardDrink'

    AND b.[CreatedDate] < a.[CreatedDate]

    )

    --== THIS ORDER BY IS VERY IMPORTANT!

    ORDER BY b.[CreatedDate] DESC

    ) ad;

    Returns: -

    UserName Drink Value CreatedDate

    -------------------- -------------------- ----------- -----------

    ABC Pepsi 50 2014-01-14

    ABC XXX 96 2014-02-06

    ABC Pepsi 510 2014-02-24

    ABC XXX 193 2014-03-03


    Forever trying to learn
    My blog - http://www.cadavre.co.uk/
    For better, quicker answers on T-SQL questions, click on the following...http://www.sqlservercentral.com/articles/Best+Practices/61537/
    For better, quicker answers on SQL Server performance related questions, click on the following...http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • Not really sure what you are trying to do here - but this is a simple way to assign numbers to the Cycles in your data set:

    ;WITH CycleEnds AS (

    SELECT UserName, CreatedDate, Cycle = ROW_NUMBER() OVER(ORDER BY CreatedDate)

    FROM #TEMP

    WHERE Drink = 'HardDrink')

    SELECT t.*, ou.Cycle

    FROM #TEMP t

    OUTER APPLY (

    SELECT TOP 1 Cycle

    FROM CycleEnds c

    WHERE c.UserName = t.UserName AND c.CreatedDate >= t.CreatedDate

    ORDER BY CreatedDate

    ) ou

    β€œWrite the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden

  • Cadavre (9/4/2014)


    JackTimber (9/4/2014)


    Hi all experts,

    I am sorry to post the problem of the same type , but i am not able to logically interpret how to traverse through the queries πŸ™

    Please see this code snippet under which i am trying to solve my problem , if possible pls help :crying:

    I've always called this kind of problem a "data smudge". Essentially, you want to smudge the data together :hehe:

    Try: -

    SELECT ad.UserName, ad.Drink, ad.Value, ad.CreatedDate

    FROM (

    SELECT UserName, Drink, Value, CreatedDate,

    MAX(CreatedDate) OVER ( ) AS MaxDate

    FROM #TEMP

    ) a

    CROSS APPLY (

    SELECT TOP 1

    b.UserName, b.Drink, b.Value, b.CreatedDate

    FROM #TEMP b

    WHERE (

    a.MaxDate = a.CreatedDate

    AND a.Drink <> 'HardDrink'

    AND a.CreatedDate = b.CreatedDate

    )

    OR (

    a.Drink = 'HardDrink'

    AND b.[CreatedDate] < a.[CreatedDate]

    )

    --== THIS ORDER BY IS VERY IMPORTANT!

    ORDER BY b.[CreatedDate] DESC

    ) ad;

    Returns: -

    UserName Drink Value CreatedDate

    -------------------- -------------------- ----------- -----------

    ABC Pepsi 50 2014-01-14

    ABC XXX 96 2014-02-06

    ABC Pepsi 510 2014-02-24

    ABC XXX 193 2014-03-03

    Thanks for the help πŸ™‚

    since yesterday i am trying to tiled your solution to solve my problem.

    As in my case there would be different user , so i put the join on UserName . Consider below for it.

    SELECT ad.UserName, ad.Drink, ad.Value, ad.CreatedDate

    FROM (

    SELECT UserName, Drink, Value, CreatedDate,

    MAX(CreatedDate) OVER ( ) AS MaxDate

    FROM #TEMP

    ) a

    CROSS APPLY (

    SELECT TOP 1

    b.UserName, b.Drink, b.Value, b.CreatedDate

    FROM #TEMP b

    WHERE a.UserName =b.UserName /*Change over here but not working,apart from cross applyi tried Out with Outer apply but it is also not working */

    (

    a.MaxDate = a.CreatedDate

    AND a.Drink <> 'HardDrink'

    AND a.CreatedDate = b.CreatedDate

    )

    OR (

    a.Drink = 'HardDrink'

    AND b.[CreatedDate] < a.[CreatedDate]

    )

    --== THIS ORDER BY IS VERY IMPORTANT!

    ORDER BY b.[CreatedDate] DESC

  • JackTimber (9/4/2014)


    Thanks for the help πŸ™‚

    since yesterday i am trying to tiled your solution to solve my problem.

    As in my case there would be different user , so i put the join on UserName . Consider below for it.

    SELECT ad.UserName, ad.Drink, ad.Value, ad.CreatedDate

    FROM (

    SELECT UserName, Drink, Value, CreatedDate,

    MAX(CreatedDate) OVER ( ) AS MaxDate

    FROM #TEMP

    ) a

    CROSS APPLY (

    SELECT TOP 1

    b.UserName, b.Drink, b.Value, b.CreatedDate

    FROM #TEMP b

    WHERE a.UserName =b.UserName /*Change over here but not working,apart from cross applyi tried Out with Outer apply but it is also not working */

    (

    a.MaxDate = a.CreatedDate

    AND a.Drink <> 'HardDrink'

    AND a.CreatedDate = b.CreatedDate

    )

    OR (

    a.Drink = 'HardDrink'

    AND b.[CreatedDate] < a.[CreatedDate]

    )

    --== THIS ORDER BY IS VERY IMPORTANT!

    ORDER BY b.[CreatedDate] DESC

    Can you include some sample data with a second user, a long with expected results please?

    I'm currently on my phone, so this is untested but I suspect you want something like this: -

    SELECT ad.UserName, ad.Drink, ad.Value, ad.CreatedDate

    FROM (

    SELECT UserName, Drink, Value, CreatedDate,

    MAX(CreatedDate) OVER ( PARTITION BY UserName ) AS MaxDate

    FROM #TEMP

    ) a

    CROSS APPLY (

    SELECT TOP 1

    b.UserName, b.Drink, b.Value, b.CreatedDate

    FROM #TEMP b

    WHERE a.UserName = b.UserName

    AND (

    a.MaxDate = a.CreatedDate

    AND a.Drink <> 'HardDrink'

    AND a.CreatedDate = b.CreatedDate

    )

    OR (

    a.Drink = 'HardDrink'

    AND b.[CreatedDate] < a.[CreatedDate]

    )

    --== THIS ORDER BY IS VERY IMPORTANT!

    ORDER BY b.[CreatedDate] DESC

    ) ad;


    Forever trying to learn
    My blog - http://www.cadavre.co.uk/
    For better, quicker answers on T-SQL questions, click on the following...http://www.sqlservercentral.com/articles/Best+Practices/61537/
    For better, quicker answers on SQL Server performance related questions, click on the following...http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

  • Thank u Cadavre for quick response.

    I am sorry to pluzzel you with my requirement. But i thought of giving myself a day and try to come up with a solution but πŸ™

    To understand please find my inline comments in the below code snippet.

    CREATE TABLE #TEMP (UserName varchar(20),Drink varchar(20),Value int,CreatedDate date)

    INSERT INTO #TEMP VALUES ('ABC','Coke',100,'2014-01-12') --Starts with coke or fanta (1st Cycle)

    INSERT INTO #TEMP VALUES ('ABC','Fanta',50,'2014-01-13')

    INSERT INTO #TEMP VALUES ('ABC','Pepsi',50,'2014-01-14')

    INSERT INTO #TEMP VALUES ('ABC','HardDrink',75,'2014-01-18') --ends with HardDrink

    INSERT INTO #TEMP VALUES ('ABC','Fanta',36,'2014-01-20') --Starts with Fanta (2nd Cycle)

    INSERT INTO #TEMP VALUES ('ABC','XXX',45,'2014-01-28')

    INSERT INTO #TEMP VALUES ('ABC','XXX',75,'2014-02-04')

    INSERT INTO #TEMP VALUES ('ABC','XXX',96,'2014-02-06')

    INSERT INTO #TEMP VALUES ('ABC','HardDrink',12,'2014-02-10') --ends with HardDrink

    INSERT INTO #TEMP VALUES ('ABC','Fanta',93,'2014-02-22') --Starts with Fanta (3rd Cycle)

    INSERT INTO #TEMP VALUES ('ABC','XXX',101,'2014-02-22')

    INSERT INTO #TEMP VALUES ('ABC','Pepsi',150,'2014-02-23')

    INSERT INTO #TEMP VALUES ('ABC','Pepsi',510,'2014-02-24')

    INSERT INTO #TEMP VALUES ('ABC','HardDrink',175,'2014-02-25') --end with HardDrink

    INSERT INTO #TEMP VALUES ('ABC','Fanta',136,'2014-02-26') --Starts with Fanta (4th Cycle)

    INSERT INTO #TEMP VALUES ('ABC','XXX',145,'2014-02-27')

    INSERT INTO #TEMP VALUES ('ABC','XXX',175,'2014-02-28')

    INSERT INTO #TEMP VALUES ('ABC','XXX',196,'2014-03-01')

    INSERT INTO #TEMP VALUES ('ABC','XXX',112,'2014-03-02')

    INSERT INTO #TEMP VALUES ('ABC','XXX',193,'2014-03-03')

    SELECT * FROM #TEMP

    /*

    1. Take record before last , from each cycle , and Value 1 and Value2 should be same if HardDrink is present

    If HardDrink is not present then consider the last record such that Value1 column should contain last

    record value and Value2 column should contain cycle start value (i.e. Coke or Fanta value)

    The Output should be as,

    UserName DrinkValue1Value2

    ABCPepsi 5050

    ABCXXX 9696

    ABCpepsi 510510

    ABCXXX193145

    */

  • Not much of a change needed from last time, adding a second conditional in the last part to allow for missing HardDrink did the trick.;-)

    😎

    USE tempdb;

    GO

    CREATE TABLE #TEMP (UserName varchar(20),Drink varchar(20),Value int,CreatedDate date)

    INSERT INTO #TEMP VALUES ('ABC','Coke',100,'2014-01-12') --Starts with coke or fanta (1st Cycle)

    INSERT INTO #TEMP VALUES ('ABC','Fanta',50,'2014-01-13')

    INSERT INTO #TEMP VALUES ('ABC','Pepsi',50,'2014-01-14')

    INSERT INTO #TEMP VALUES ('ABC','HardDrink',75,'2014-01-18') --ends with HardDrink

    INSERT INTO #TEMP VALUES ('ABC','Fanta',36,'2014-01-20') --Starts with Fanta (2nd Cycle)

    INSERT INTO #TEMP VALUES ('ABC','XXX',45,'2014-01-28')

    INSERT INTO #TEMP VALUES ('ABC','XXX',75,'2014-02-04')

    INSERT INTO #TEMP VALUES ('ABC','XXX',96,'2014-02-06')

    INSERT INTO #TEMP VALUES ('ABC','HardDrink',12,'2014-02-10') --ends with HardDrink

    INSERT INTO #TEMP VALUES ('ABC','Fanta',93,'2014-02-22') --Starts with Fanta (3rd Cycle)

    INSERT INTO #TEMP VALUES ('ABC','XXX',101,'2014-02-22')

    INSERT INTO #TEMP VALUES ('ABC','Pepsi',150,'2014-02-23')

    INSERT INTO #TEMP VALUES ('ABC','Pepsi',510,'2014-02-24')

    INSERT INTO #TEMP VALUES ('ABC','HardDrink',175,'2014-02-25') --end with HardDrink

    INSERT INTO #TEMP VALUES ('ABC','Fanta',136,'2014-02-26') --Starts with Fanta (4th Cycle)

    INSERT INTO #TEMP VALUES ('ABC','XXX',145,'2014-02-27')

    INSERT INTO #TEMP VALUES ('ABC','XXX',175,'2014-02-28')

    INSERT INTO #TEMP VALUES ('ABC','XXX',196,'2014-03-01')

    INSERT INTO #TEMP VALUES ('ABC','XXX',112,'2014-03-02')

    INSERT INTO #TEMP VALUES ('ABC','XXX',193,'2014-03-03');

    ;WITH BASE_DATA AS

    (

    SELECT

    ROW_NUMBER() OVER (ORDER BY T.CreatedDate) AS T_RID

    ,T.UserName

    ,T.Drink

    ,T.Value

    ,T.CreatedDate

    FROM #TEMP T

    )

    SELECT

    BD.UserName

    ,BD.Drink

    ,BD.Value

    ,BD.CreatedDate

    FROM BASE_DATA BD

    LEFT OUTER JOIN BASE_DATA BLEAD

    ON BD.T_RID = BLEAD.T_RID - 1

    WHERE BLEAD.Drink = 'HardDrink'

    OR BLEAD.Drink IS NULL;

    DROP TABLE #TEMP

    Results

    UserName Drink Value CreatedDate

    -------------------- -------------------- ----------- -----------

    ABC Pepsi 50 2014-01-14

    ABC XXX 96 2014-02-06

    ABC Pepsi 510 2014-02-24

    ABC XXX 193 2014-03-03

  • JackTimber (9/5/2014)


    Thank u Cadavre for quick response.

    I am sorry to pluzzel you with my requirement. But i thought of giving myself a day and try to come up with a solution but πŸ™

    To understand please find my inline comments in the below code snippet.

    Sorry for the late reply.

    You haven't actually included the hypothetical second user in your new sample data, my original code works on this new sample data.


    Forever trying to learn
    My blog - http://www.cadavre.co.uk/
    For better, quicker answers on T-SQL questions, click on the following...http://www.sqlservercentral.com/articles/Best+Practices/61537/
    For better, quicker answers on SQL Server performance related questions, click on the following...http://www.sqlservercentral.com/articles/SQLServerCentral/66909/

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

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