How to integrate while loop into SQL query? (Repeating last result in the column)'IF' in 'SELECT' statement - choose output value based on column valuesHow to check if a column exists in a SQL Server table?How do you change the datatype of a column in SQL Server?How to replace a string in a SQL Server Table ColumnHow can I get column names from a table in SQL Server?How to set variable from a SQL query?SQL Query OptimizationSQL While Loop 60 seconds?Why am I getting a syntax error near keyword 'with'?MS SQL: return HTML from SQL PIVOT RESULTS with dynamic name/number of columnsSQL Server Management Studio using While loop function to split result

Can my floppy disk still work without a shutter spring?

Looking for a soft substance that doesn't dissolve underwater

Website returning plaintext password

How strong are Wi-Fi signals?

Why did the person in charge of a principality not just declare themself king?

Need to understand my home electrical meter to see why bill is so high and/or if neighbor is on same meter

What is the object moving across the ceiling in this stock footage?

How to use libraries with delays inside within a time critical STM32 HAL application?

Why did Theresa May offer a vote on a second Brexit referendum?

Python program to take in two strings and print the larger string

Make 24 using exactly three 3s

Can a person survive on blood in place of water?

How to respond to an upset student?

What is the difference between singing and speaking?

Is it true that cut time means "play twice as fast as written"?

Can I tell a prospective employee that everyone in the team is leaving?

Count Even Digits In Number

What to keep in mind when telling an aunt how wrong her actions are, without creating further family conflict?

Underbrace equation issues

In general, would I need to season a meat when making a sauce?

Teacher help me explain this to my students

Using credit/debit card details vs swiping a card in a payment (credit card) terminal

Breaking down doors - AC or DC?

How should I introduce map drawing to my players?



How to integrate while loop into SQL query? (Repeating last result in the column)


'IF' in 'SELECT' statement - choose output value based on column valuesHow to check if a column exists in a SQL Server table?How do you change the datatype of a column in SQL Server?How to replace a string in a SQL Server Table ColumnHow can I get column names from a table in SQL Server?How to set variable from a SQL query?SQL Query OptimizationSQL While Loop 60 seconds?Why am I getting a syntax error near keyword 'with'?MS SQL: return HTML from SQL PIVOT RESULTS with dynamic name/number of columnsSQL Server Management Studio using While loop function to split result






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








1















I'm trying to build a query in SQL Server Management Studio using a while loop to obtain the final Result column.



Let say I already have a query (My_query) where I am extracting the following information.



Output sample



My_query is giving me already all the information below without the Result column. My plan was to include a while loop that allows me to identify the correct status for each Period and ID. The logic I was trying to use was the following:



Declare i int = 0
Declare j int = 0
Declare buffer int = 0

With My_query as (My query code is here)

Select *,
Result =

while (i <= 12) --This will be the number of rows coming from My_query.
Begin
set buffer = 0 -- Resetting the status variable for the next ID
while (j <= 6) -- This will be the number of periods for every ID. Max(Block)
Begin
If (Block = 1 and Status_History IS NULL) -- Block = 1 always will be the higher period consulted in My_query.
Set Result = Current_Status
Set buffer = Result
If (Block = 1 and Status_History IS NOT NULL)
Set Result = Status_History
Set buffer = Result
If (Block <> 1 and Status_History IS NULL)
Set Result = buffer
If (Block <> 1 and Status_History IS NOT NULL)
Set Result = Status_History
Set buffer = Result
Set j = j+1
END
Set i = i+1
END
From My_query


Solution:
The best way I found to solve this problem was creating an index (besides the "Block" one) that allows me to identify specific changes by group. The index assign 0 to NULL values and every time a value different than NULL is found it SUM 1 to the index. When the ID change, the index reset. This solution is way lighter on resources consumption.



Index



SUM(CASE 
WHEN(Status_History) IS NULL THEN 0 ELSE 1 END) OVER (PARTITION BY ID ORDER BY Period DESC) AS IND


Solution



WITH DAT AS (My_query)

SELECT *,
CASE WHEN IND = 0 THEN DAT.Current_Status ELSE MAX(DAT.Status_History) OVER ( PARTITION BY DAT.ID, DAT.IND ORDER BY DAT.Period DESC) END AS Result
FROM DAT
ORDER BY ID, Period DESC


 ID Period Current_Status Status_History IND Block Result
1012 201903 32 NULL 0 1 32
1012 201902 32 NULL 0 2 32
1012 201901 32 16 1 3 16
1012 201812 32 NULL 1 4 16
1012 201811 32 NULL 1 5 16
1012 201810 32 10 2 6 10
1012 201809 32 NULL 2 7 10
5124 201903 25 NULL 0 1 25
5124 201902 25 23 2 2 23
5124 201901 25 29 3 3 29
5124 201812 25 NULL 4 4 29
5124 201811 25 NULL 5 5 29
5124 201810 25 NULL 6 6 29
5124 201809 25 NULL 7 7 29


Thank you all!










share|improve this question






























    1















    I'm trying to build a query in SQL Server Management Studio using a while loop to obtain the final Result column.



    Let say I already have a query (My_query) where I am extracting the following information.



    Output sample



    My_query is giving me already all the information below without the Result column. My plan was to include a while loop that allows me to identify the correct status for each Period and ID. The logic I was trying to use was the following:



    Declare i int = 0
    Declare j int = 0
    Declare buffer int = 0

    With My_query as (My query code is here)

    Select *,
    Result =

    while (i <= 12) --This will be the number of rows coming from My_query.
    Begin
    set buffer = 0 -- Resetting the status variable for the next ID
    while (j <= 6) -- This will be the number of periods for every ID. Max(Block)
    Begin
    If (Block = 1 and Status_History IS NULL) -- Block = 1 always will be the higher period consulted in My_query.
    Set Result = Current_Status
    Set buffer = Result
    If (Block = 1 and Status_History IS NOT NULL)
    Set Result = Status_History
    Set buffer = Result
    If (Block <> 1 and Status_History IS NULL)
    Set Result = buffer
    If (Block <> 1 and Status_History IS NOT NULL)
    Set Result = Status_History
    Set buffer = Result
    Set j = j+1
    END
    Set i = i+1
    END
    From My_query


    Solution:
    The best way I found to solve this problem was creating an index (besides the "Block" one) that allows me to identify specific changes by group. The index assign 0 to NULL values and every time a value different than NULL is found it SUM 1 to the index. When the ID change, the index reset. This solution is way lighter on resources consumption.



    Index



    SUM(CASE 
    WHEN(Status_History) IS NULL THEN 0 ELSE 1 END) OVER (PARTITION BY ID ORDER BY Period DESC) AS IND


    Solution



    WITH DAT AS (My_query)

    SELECT *,
    CASE WHEN IND = 0 THEN DAT.Current_Status ELSE MAX(DAT.Status_History) OVER ( PARTITION BY DAT.ID, DAT.IND ORDER BY DAT.Period DESC) END AS Result
    FROM DAT
    ORDER BY ID, Period DESC


     ID Period Current_Status Status_History IND Block Result
    1012 201903 32 NULL 0 1 32
    1012 201902 32 NULL 0 2 32
    1012 201901 32 16 1 3 16
    1012 201812 32 NULL 1 4 16
    1012 201811 32 NULL 1 5 16
    1012 201810 32 10 2 6 10
    1012 201809 32 NULL 2 7 10
    5124 201903 25 NULL 0 1 25
    5124 201902 25 23 2 2 23
    5124 201901 25 29 3 3 29
    5124 201812 25 NULL 4 4 29
    5124 201811 25 NULL 5 5 29
    5124 201810 25 NULL 6 6 29
    5124 201809 25 NULL 7 7 29


    Thank you all!










    share|improve this question


























      1












      1








      1








      I'm trying to build a query in SQL Server Management Studio using a while loop to obtain the final Result column.



      Let say I already have a query (My_query) where I am extracting the following information.



      Output sample



      My_query is giving me already all the information below without the Result column. My plan was to include a while loop that allows me to identify the correct status for each Period and ID. The logic I was trying to use was the following:



      Declare i int = 0
      Declare j int = 0
      Declare buffer int = 0

      With My_query as (My query code is here)

      Select *,
      Result =

      while (i <= 12) --This will be the number of rows coming from My_query.
      Begin
      set buffer = 0 -- Resetting the status variable for the next ID
      while (j <= 6) -- This will be the number of periods for every ID. Max(Block)
      Begin
      If (Block = 1 and Status_History IS NULL) -- Block = 1 always will be the higher period consulted in My_query.
      Set Result = Current_Status
      Set buffer = Result
      If (Block = 1 and Status_History IS NOT NULL)
      Set Result = Status_History
      Set buffer = Result
      If (Block <> 1 and Status_History IS NULL)
      Set Result = buffer
      If (Block <> 1 and Status_History IS NOT NULL)
      Set Result = Status_History
      Set buffer = Result
      Set j = j+1
      END
      Set i = i+1
      END
      From My_query


      Solution:
      The best way I found to solve this problem was creating an index (besides the "Block" one) that allows me to identify specific changes by group. The index assign 0 to NULL values and every time a value different than NULL is found it SUM 1 to the index. When the ID change, the index reset. This solution is way lighter on resources consumption.



      Index



      SUM(CASE 
      WHEN(Status_History) IS NULL THEN 0 ELSE 1 END) OVER (PARTITION BY ID ORDER BY Period DESC) AS IND


      Solution



      WITH DAT AS (My_query)

      SELECT *,
      CASE WHEN IND = 0 THEN DAT.Current_Status ELSE MAX(DAT.Status_History) OVER ( PARTITION BY DAT.ID, DAT.IND ORDER BY DAT.Period DESC) END AS Result
      FROM DAT
      ORDER BY ID, Period DESC


       ID Period Current_Status Status_History IND Block Result
      1012 201903 32 NULL 0 1 32
      1012 201902 32 NULL 0 2 32
      1012 201901 32 16 1 3 16
      1012 201812 32 NULL 1 4 16
      1012 201811 32 NULL 1 5 16
      1012 201810 32 10 2 6 10
      1012 201809 32 NULL 2 7 10
      5124 201903 25 NULL 0 1 25
      5124 201902 25 23 2 2 23
      5124 201901 25 29 3 3 29
      5124 201812 25 NULL 4 4 29
      5124 201811 25 NULL 5 5 29
      5124 201810 25 NULL 6 6 29
      5124 201809 25 NULL 7 7 29


      Thank you all!










      share|improve this question
















      I'm trying to build a query in SQL Server Management Studio using a while loop to obtain the final Result column.



      Let say I already have a query (My_query) where I am extracting the following information.



      Output sample



      My_query is giving me already all the information below without the Result column. My plan was to include a while loop that allows me to identify the correct status for each Period and ID. The logic I was trying to use was the following:



      Declare i int = 0
      Declare j int = 0
      Declare buffer int = 0

      With My_query as (My query code is here)

      Select *,
      Result =

      while (i <= 12) --This will be the number of rows coming from My_query.
      Begin
      set buffer = 0 -- Resetting the status variable for the next ID
      while (j <= 6) -- This will be the number of periods for every ID. Max(Block)
      Begin
      If (Block = 1 and Status_History IS NULL) -- Block = 1 always will be the higher period consulted in My_query.
      Set Result = Current_Status
      Set buffer = Result
      If (Block = 1 and Status_History IS NOT NULL)
      Set Result = Status_History
      Set buffer = Result
      If (Block <> 1 and Status_History IS NULL)
      Set Result = buffer
      If (Block <> 1 and Status_History IS NOT NULL)
      Set Result = Status_History
      Set buffer = Result
      Set j = j+1
      END
      Set i = i+1
      END
      From My_query


      Solution:
      The best way I found to solve this problem was creating an index (besides the "Block" one) that allows me to identify specific changes by group. The index assign 0 to NULL values and every time a value different than NULL is found it SUM 1 to the index. When the ID change, the index reset. This solution is way lighter on resources consumption.



      Index



      SUM(CASE 
      WHEN(Status_History) IS NULL THEN 0 ELSE 1 END) OVER (PARTITION BY ID ORDER BY Period DESC) AS IND


      Solution



      WITH DAT AS (My_query)

      SELECT *,
      CASE WHEN IND = 0 THEN DAT.Current_Status ELSE MAX(DAT.Status_History) OVER ( PARTITION BY DAT.ID, DAT.IND ORDER BY DAT.Period DESC) END AS Result
      FROM DAT
      ORDER BY ID, Period DESC


       ID Period Current_Status Status_History IND Block Result
      1012 201903 32 NULL 0 1 32
      1012 201902 32 NULL 0 2 32
      1012 201901 32 16 1 3 16
      1012 201812 32 NULL 1 4 16
      1012 201811 32 NULL 1 5 16
      1012 201810 32 10 2 6 10
      1012 201809 32 NULL 2 7 10
      5124 201903 25 NULL 0 1 25
      5124 201902 25 23 2 2 23
      5124 201901 25 29 3 3 29
      5124 201812 25 NULL 4 4 29
      5124 201811 25 NULL 5 5 29
      5124 201810 25 NULL 6 6 29
      5124 201809 25 NULL 7 7 29


      Thank you all!







      sql-server






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Mar 27 at 17:56







      Regressionist

















      asked Mar 24 at 3:43









      RegressionistRegressionist

      63




      63






















          2 Answers
          2






          active

          oldest

          votes


















          1














          You do not actually need a loop to iterate through the result set as functions in the SELECT statement are executed on each result record.



          You can use Control Flow Functions as described in the MySQL documentation page to handle the relevant data in your result. There are some examples of this in this stackoverflow question 'IF' in 'SELECT' statement - choose output value based on column values or you can also use a combination of the different Data combination statements in MySQL



          I did have success getting the expected output based on the image you provided by using a combination of UNION, JOIN and subqueries.



          Code




          SELECT *, mqa.Current_Status as Result
          FROM MyQuery mqa
          WHERE
          mqa.Block = 1
          AND mqa.Status_History IS NULL
          UNION
          SELECT mqb.*, mqb.Status_History as Result
          FROM MyQuery mqb
          WHERE
          Status_History IS NOT NULL
          UNION
          SELECT mqc.ID,
          mqc.Period,
          mqc.Current_Status,
          mqc.Status_History,
          mqc.Block,
          (SELECT TOP 1 mqd.Status_History FROM MyQuery mqd
          WHERE mqd.ID = mqc.ID
          AND mqd.Block < mqc.Block
          AND mqd.Status_History IS NOT NULL
          ORDER BY Block DESC)
          FROM MyQuery mqc
          WHERE
          mqc.Status_History IS NULL
          AND mqc.Block <> 1


          Results



          | ID | Period | Current_Status | Status_History | Block | Result |
          |--------|--------|----------------|----------------|-------|--------|
          | 012014 | 201710 | 5 | (null) | 6 | 7 |
          | 012014 | 201711 | 5 | 7 | 5 | 7 |
          | 012014 | 201712 | 5 | (null) | 4 | 3 |
          | 012014 | 201810 | 5 | (null) | 3 | 3 |
          | 012014 | 201811 | 5 | 3 | 2 | 3 |
          | 012014 | 201812 | 5 | (null) | 1 | 5 |
          | 012015 | 201710 | 2 | (null) | 6 | 10 |
          | 012015 | 201711 | 2 | (null) | 5 | 10 |
          | 012015 | 201712 | 2 | (null) | 4 | 10 |
          | 012015 | 201810 | 2 | (null) | 3 | 10 |
          | 012015 | 201811 | 2 | (null) | 2 | 10 |
          | 012015 | 201812 | 2 | 10 | 1 | 10 |


          You can play with the code above in this SQLFiddle






          share|improve this answer

























          • Thank you for your response, I really like the logic you're using here and I think it can be less time consuming than using a while loop. I have to things to point out: Fisrt: I'm getting the following error: Column 'MyQuery.Current_Status' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

            – Regressionist
            Mar 25 at 13:55











          • Second: Could you explain me in more detail what is logic in this point: SELECT a.*,MAX(b.Status_History) as Result FROM MyQuery a JOIN MyQuery b ON b.ID = a.ID AND b.Block < a.Block AND b.Status_History IS NOT NULL WHERE a.Status_History IS NULL AND a.Block <> 1 GROUP BY a.ID, a.Period)

            – Regressionist
            Mar 25 at 13:55











          • BTW, I saw you were using MySQL 5.6 on the SQL Fiddle platform. I changed to SQL Server and now the error is being shown in the example as well.

            – Regressionist
            Mar 25 at 15:19











          • Update: I was able to get results including all the columns in the group by clause. The issue now is, because the code is using MAX(b.Status_History) cases where the status starts with a larger number the result is miss classify until it finds a larger value or the ID change.

            – Regressionist
            Mar 25 at 20:47











          • The whole point of my answer was for you to take a look at Subqueries, JOIN, and UNION statements and not use loops because it is very unnecessary. I updated the query for you, the updated query will take into account Status_History which start out with greater numbers than the ones in the later blocks.

            – Ian Preglo
            Mar 26 at 14:14


















          0














          It seems like you are falling back on the first non-null value of the previous record when a condition is not met. In theory this could be a coalesce result of the previous values and the current values looking for the first non-null in the desired order.



          With My_query as (My query code is here)

          SELECT i,Block,
          Result =
          CASE WHEN (Block=1) THEN
          COALESCE(Status_History,Current_History)
          ELSE
          COALESCE(Status_History, LAG(Status_History) OVER (PARTITION BY Block ORDER BY i),LAG(Current_Status) OVER (PARTITION BY Block ORDER BY i)
          END
          FROM
          My_Query





          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55320542%2fhow-to-integrate-while-loop-into-sql-query-repeating-last-result-in-the-column%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            You do not actually need a loop to iterate through the result set as functions in the SELECT statement are executed on each result record.



            You can use Control Flow Functions as described in the MySQL documentation page to handle the relevant data in your result. There are some examples of this in this stackoverflow question 'IF' in 'SELECT' statement - choose output value based on column values or you can also use a combination of the different Data combination statements in MySQL



            I did have success getting the expected output based on the image you provided by using a combination of UNION, JOIN and subqueries.



            Code




            SELECT *, mqa.Current_Status as Result
            FROM MyQuery mqa
            WHERE
            mqa.Block = 1
            AND mqa.Status_History IS NULL
            UNION
            SELECT mqb.*, mqb.Status_History as Result
            FROM MyQuery mqb
            WHERE
            Status_History IS NOT NULL
            UNION
            SELECT mqc.ID,
            mqc.Period,
            mqc.Current_Status,
            mqc.Status_History,
            mqc.Block,
            (SELECT TOP 1 mqd.Status_History FROM MyQuery mqd
            WHERE mqd.ID = mqc.ID
            AND mqd.Block < mqc.Block
            AND mqd.Status_History IS NOT NULL
            ORDER BY Block DESC)
            FROM MyQuery mqc
            WHERE
            mqc.Status_History IS NULL
            AND mqc.Block <> 1


            Results



            | ID | Period | Current_Status | Status_History | Block | Result |
            |--------|--------|----------------|----------------|-------|--------|
            | 012014 | 201710 | 5 | (null) | 6 | 7 |
            | 012014 | 201711 | 5 | 7 | 5 | 7 |
            | 012014 | 201712 | 5 | (null) | 4 | 3 |
            | 012014 | 201810 | 5 | (null) | 3 | 3 |
            | 012014 | 201811 | 5 | 3 | 2 | 3 |
            | 012014 | 201812 | 5 | (null) | 1 | 5 |
            | 012015 | 201710 | 2 | (null) | 6 | 10 |
            | 012015 | 201711 | 2 | (null) | 5 | 10 |
            | 012015 | 201712 | 2 | (null) | 4 | 10 |
            | 012015 | 201810 | 2 | (null) | 3 | 10 |
            | 012015 | 201811 | 2 | (null) | 2 | 10 |
            | 012015 | 201812 | 2 | 10 | 1 | 10 |


            You can play with the code above in this SQLFiddle






            share|improve this answer

























            • Thank you for your response, I really like the logic you're using here and I think it can be less time consuming than using a while loop. I have to things to point out: Fisrt: I'm getting the following error: Column 'MyQuery.Current_Status' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

              – Regressionist
              Mar 25 at 13:55











            • Second: Could you explain me in more detail what is logic in this point: SELECT a.*,MAX(b.Status_History) as Result FROM MyQuery a JOIN MyQuery b ON b.ID = a.ID AND b.Block < a.Block AND b.Status_History IS NOT NULL WHERE a.Status_History IS NULL AND a.Block <> 1 GROUP BY a.ID, a.Period)

              – Regressionist
              Mar 25 at 13:55











            • BTW, I saw you were using MySQL 5.6 on the SQL Fiddle platform. I changed to SQL Server and now the error is being shown in the example as well.

              – Regressionist
              Mar 25 at 15:19











            • Update: I was able to get results including all the columns in the group by clause. The issue now is, because the code is using MAX(b.Status_History) cases where the status starts with a larger number the result is miss classify until it finds a larger value or the ID change.

              – Regressionist
              Mar 25 at 20:47











            • The whole point of my answer was for you to take a look at Subqueries, JOIN, and UNION statements and not use loops because it is very unnecessary. I updated the query for you, the updated query will take into account Status_History which start out with greater numbers than the ones in the later blocks.

              – Ian Preglo
              Mar 26 at 14:14















            1














            You do not actually need a loop to iterate through the result set as functions in the SELECT statement are executed on each result record.



            You can use Control Flow Functions as described in the MySQL documentation page to handle the relevant data in your result. There are some examples of this in this stackoverflow question 'IF' in 'SELECT' statement - choose output value based on column values or you can also use a combination of the different Data combination statements in MySQL



            I did have success getting the expected output based on the image you provided by using a combination of UNION, JOIN and subqueries.



            Code




            SELECT *, mqa.Current_Status as Result
            FROM MyQuery mqa
            WHERE
            mqa.Block = 1
            AND mqa.Status_History IS NULL
            UNION
            SELECT mqb.*, mqb.Status_History as Result
            FROM MyQuery mqb
            WHERE
            Status_History IS NOT NULL
            UNION
            SELECT mqc.ID,
            mqc.Period,
            mqc.Current_Status,
            mqc.Status_History,
            mqc.Block,
            (SELECT TOP 1 mqd.Status_History FROM MyQuery mqd
            WHERE mqd.ID = mqc.ID
            AND mqd.Block < mqc.Block
            AND mqd.Status_History IS NOT NULL
            ORDER BY Block DESC)
            FROM MyQuery mqc
            WHERE
            mqc.Status_History IS NULL
            AND mqc.Block <> 1


            Results



            | ID | Period | Current_Status | Status_History | Block | Result |
            |--------|--------|----------------|----------------|-------|--------|
            | 012014 | 201710 | 5 | (null) | 6 | 7 |
            | 012014 | 201711 | 5 | 7 | 5 | 7 |
            | 012014 | 201712 | 5 | (null) | 4 | 3 |
            | 012014 | 201810 | 5 | (null) | 3 | 3 |
            | 012014 | 201811 | 5 | 3 | 2 | 3 |
            | 012014 | 201812 | 5 | (null) | 1 | 5 |
            | 012015 | 201710 | 2 | (null) | 6 | 10 |
            | 012015 | 201711 | 2 | (null) | 5 | 10 |
            | 012015 | 201712 | 2 | (null) | 4 | 10 |
            | 012015 | 201810 | 2 | (null) | 3 | 10 |
            | 012015 | 201811 | 2 | (null) | 2 | 10 |
            | 012015 | 201812 | 2 | 10 | 1 | 10 |


            You can play with the code above in this SQLFiddle






            share|improve this answer

























            • Thank you for your response, I really like the logic you're using here and I think it can be less time consuming than using a while loop. I have to things to point out: Fisrt: I'm getting the following error: Column 'MyQuery.Current_Status' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

              – Regressionist
              Mar 25 at 13:55











            • Second: Could you explain me in more detail what is logic in this point: SELECT a.*,MAX(b.Status_History) as Result FROM MyQuery a JOIN MyQuery b ON b.ID = a.ID AND b.Block < a.Block AND b.Status_History IS NOT NULL WHERE a.Status_History IS NULL AND a.Block <> 1 GROUP BY a.ID, a.Period)

              – Regressionist
              Mar 25 at 13:55











            • BTW, I saw you were using MySQL 5.6 on the SQL Fiddle platform. I changed to SQL Server and now the error is being shown in the example as well.

              – Regressionist
              Mar 25 at 15:19











            • Update: I was able to get results including all the columns in the group by clause. The issue now is, because the code is using MAX(b.Status_History) cases where the status starts with a larger number the result is miss classify until it finds a larger value or the ID change.

              – Regressionist
              Mar 25 at 20:47











            • The whole point of my answer was for you to take a look at Subqueries, JOIN, and UNION statements and not use loops because it is very unnecessary. I updated the query for you, the updated query will take into account Status_History which start out with greater numbers than the ones in the later blocks.

              – Ian Preglo
              Mar 26 at 14:14













            1












            1








            1







            You do not actually need a loop to iterate through the result set as functions in the SELECT statement are executed on each result record.



            You can use Control Flow Functions as described in the MySQL documentation page to handle the relevant data in your result. There are some examples of this in this stackoverflow question 'IF' in 'SELECT' statement - choose output value based on column values or you can also use a combination of the different Data combination statements in MySQL



            I did have success getting the expected output based on the image you provided by using a combination of UNION, JOIN and subqueries.



            Code




            SELECT *, mqa.Current_Status as Result
            FROM MyQuery mqa
            WHERE
            mqa.Block = 1
            AND mqa.Status_History IS NULL
            UNION
            SELECT mqb.*, mqb.Status_History as Result
            FROM MyQuery mqb
            WHERE
            Status_History IS NOT NULL
            UNION
            SELECT mqc.ID,
            mqc.Period,
            mqc.Current_Status,
            mqc.Status_History,
            mqc.Block,
            (SELECT TOP 1 mqd.Status_History FROM MyQuery mqd
            WHERE mqd.ID = mqc.ID
            AND mqd.Block < mqc.Block
            AND mqd.Status_History IS NOT NULL
            ORDER BY Block DESC)
            FROM MyQuery mqc
            WHERE
            mqc.Status_History IS NULL
            AND mqc.Block <> 1


            Results



            | ID | Period | Current_Status | Status_History | Block | Result |
            |--------|--------|----------------|----------------|-------|--------|
            | 012014 | 201710 | 5 | (null) | 6 | 7 |
            | 012014 | 201711 | 5 | 7 | 5 | 7 |
            | 012014 | 201712 | 5 | (null) | 4 | 3 |
            | 012014 | 201810 | 5 | (null) | 3 | 3 |
            | 012014 | 201811 | 5 | 3 | 2 | 3 |
            | 012014 | 201812 | 5 | (null) | 1 | 5 |
            | 012015 | 201710 | 2 | (null) | 6 | 10 |
            | 012015 | 201711 | 2 | (null) | 5 | 10 |
            | 012015 | 201712 | 2 | (null) | 4 | 10 |
            | 012015 | 201810 | 2 | (null) | 3 | 10 |
            | 012015 | 201811 | 2 | (null) | 2 | 10 |
            | 012015 | 201812 | 2 | 10 | 1 | 10 |


            You can play with the code above in this SQLFiddle






            share|improve this answer















            You do not actually need a loop to iterate through the result set as functions in the SELECT statement are executed on each result record.



            You can use Control Flow Functions as described in the MySQL documentation page to handle the relevant data in your result. There are some examples of this in this stackoverflow question 'IF' in 'SELECT' statement - choose output value based on column values or you can also use a combination of the different Data combination statements in MySQL



            I did have success getting the expected output based on the image you provided by using a combination of UNION, JOIN and subqueries.



            Code




            SELECT *, mqa.Current_Status as Result
            FROM MyQuery mqa
            WHERE
            mqa.Block = 1
            AND mqa.Status_History IS NULL
            UNION
            SELECT mqb.*, mqb.Status_History as Result
            FROM MyQuery mqb
            WHERE
            Status_History IS NOT NULL
            UNION
            SELECT mqc.ID,
            mqc.Period,
            mqc.Current_Status,
            mqc.Status_History,
            mqc.Block,
            (SELECT TOP 1 mqd.Status_History FROM MyQuery mqd
            WHERE mqd.ID = mqc.ID
            AND mqd.Block < mqc.Block
            AND mqd.Status_History IS NOT NULL
            ORDER BY Block DESC)
            FROM MyQuery mqc
            WHERE
            mqc.Status_History IS NULL
            AND mqc.Block <> 1


            Results



            | ID | Period | Current_Status | Status_History | Block | Result |
            |--------|--------|----------------|----------------|-------|--------|
            | 012014 | 201710 | 5 | (null) | 6 | 7 |
            | 012014 | 201711 | 5 | 7 | 5 | 7 |
            | 012014 | 201712 | 5 | (null) | 4 | 3 |
            | 012014 | 201810 | 5 | (null) | 3 | 3 |
            | 012014 | 201811 | 5 | 3 | 2 | 3 |
            | 012014 | 201812 | 5 | (null) | 1 | 5 |
            | 012015 | 201710 | 2 | (null) | 6 | 10 |
            | 012015 | 201711 | 2 | (null) | 5 | 10 |
            | 012015 | 201712 | 2 | (null) | 4 | 10 |
            | 012015 | 201810 | 2 | (null) | 3 | 10 |
            | 012015 | 201811 | 2 | (null) | 2 | 10 |
            | 012015 | 201812 | 2 | 10 | 1 | 10 |


            You can play with the code above in this SQLFiddle







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Mar 26 at 14:31

























            answered Mar 24 at 7:33









            Ian PregloIan Preglo

            30410




            30410












            • Thank you for your response, I really like the logic you're using here and I think it can be less time consuming than using a while loop. I have to things to point out: Fisrt: I'm getting the following error: Column 'MyQuery.Current_Status' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

              – Regressionist
              Mar 25 at 13:55











            • Second: Could you explain me in more detail what is logic in this point: SELECT a.*,MAX(b.Status_History) as Result FROM MyQuery a JOIN MyQuery b ON b.ID = a.ID AND b.Block < a.Block AND b.Status_History IS NOT NULL WHERE a.Status_History IS NULL AND a.Block <> 1 GROUP BY a.ID, a.Period)

              – Regressionist
              Mar 25 at 13:55











            • BTW, I saw you were using MySQL 5.6 on the SQL Fiddle platform. I changed to SQL Server and now the error is being shown in the example as well.

              – Regressionist
              Mar 25 at 15:19











            • Update: I was able to get results including all the columns in the group by clause. The issue now is, because the code is using MAX(b.Status_History) cases where the status starts with a larger number the result is miss classify until it finds a larger value or the ID change.

              – Regressionist
              Mar 25 at 20:47











            • The whole point of my answer was for you to take a look at Subqueries, JOIN, and UNION statements and not use loops because it is very unnecessary. I updated the query for you, the updated query will take into account Status_History which start out with greater numbers than the ones in the later blocks.

              – Ian Preglo
              Mar 26 at 14:14

















            • Thank you for your response, I really like the logic you're using here and I think it can be less time consuming than using a while loop. I have to things to point out: Fisrt: I'm getting the following error: Column 'MyQuery.Current_Status' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

              – Regressionist
              Mar 25 at 13:55











            • Second: Could you explain me in more detail what is logic in this point: SELECT a.*,MAX(b.Status_History) as Result FROM MyQuery a JOIN MyQuery b ON b.ID = a.ID AND b.Block < a.Block AND b.Status_History IS NOT NULL WHERE a.Status_History IS NULL AND a.Block <> 1 GROUP BY a.ID, a.Period)

              – Regressionist
              Mar 25 at 13:55











            • BTW, I saw you were using MySQL 5.6 on the SQL Fiddle platform. I changed to SQL Server and now the error is being shown in the example as well.

              – Regressionist
              Mar 25 at 15:19











            • Update: I was able to get results including all the columns in the group by clause. The issue now is, because the code is using MAX(b.Status_History) cases where the status starts with a larger number the result is miss classify until it finds a larger value or the ID change.

              – Regressionist
              Mar 25 at 20:47











            • The whole point of my answer was for you to take a look at Subqueries, JOIN, and UNION statements and not use loops because it is very unnecessary. I updated the query for you, the updated query will take into account Status_History which start out with greater numbers than the ones in the later blocks.

              – Ian Preglo
              Mar 26 at 14:14
















            Thank you for your response, I really like the logic you're using here and I think it can be less time consuming than using a while loop. I have to things to point out: Fisrt: I'm getting the following error: Column 'MyQuery.Current_Status' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

            – Regressionist
            Mar 25 at 13:55





            Thank you for your response, I really like the logic you're using here and I think it can be less time consuming than using a while loop. I have to things to point out: Fisrt: I'm getting the following error: Column 'MyQuery.Current_Status' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

            – Regressionist
            Mar 25 at 13:55













            Second: Could you explain me in more detail what is logic in this point: SELECT a.*,MAX(b.Status_History) as Result FROM MyQuery a JOIN MyQuery b ON b.ID = a.ID AND b.Block < a.Block AND b.Status_History IS NOT NULL WHERE a.Status_History IS NULL AND a.Block <> 1 GROUP BY a.ID, a.Period)

            – Regressionist
            Mar 25 at 13:55





            Second: Could you explain me in more detail what is logic in this point: SELECT a.*,MAX(b.Status_History) as Result FROM MyQuery a JOIN MyQuery b ON b.ID = a.ID AND b.Block < a.Block AND b.Status_History IS NOT NULL WHERE a.Status_History IS NULL AND a.Block <> 1 GROUP BY a.ID, a.Period)

            – Regressionist
            Mar 25 at 13:55













            BTW, I saw you were using MySQL 5.6 on the SQL Fiddle platform. I changed to SQL Server and now the error is being shown in the example as well.

            – Regressionist
            Mar 25 at 15:19





            BTW, I saw you were using MySQL 5.6 on the SQL Fiddle platform. I changed to SQL Server and now the error is being shown in the example as well.

            – Regressionist
            Mar 25 at 15:19













            Update: I was able to get results including all the columns in the group by clause. The issue now is, because the code is using MAX(b.Status_History) cases where the status starts with a larger number the result is miss classify until it finds a larger value or the ID change.

            – Regressionist
            Mar 25 at 20:47





            Update: I was able to get results including all the columns in the group by clause. The issue now is, because the code is using MAX(b.Status_History) cases where the status starts with a larger number the result is miss classify until it finds a larger value or the ID change.

            – Regressionist
            Mar 25 at 20:47













            The whole point of my answer was for you to take a look at Subqueries, JOIN, and UNION statements and not use loops because it is very unnecessary. I updated the query for you, the updated query will take into account Status_History which start out with greater numbers than the ones in the later blocks.

            – Ian Preglo
            Mar 26 at 14:14





            The whole point of my answer was for you to take a look at Subqueries, JOIN, and UNION statements and not use loops because it is very unnecessary. I updated the query for you, the updated query will take into account Status_History which start out with greater numbers than the ones in the later blocks.

            – Ian Preglo
            Mar 26 at 14:14













            0














            It seems like you are falling back on the first non-null value of the previous record when a condition is not met. In theory this could be a coalesce result of the previous values and the current values looking for the first non-null in the desired order.



            With My_query as (My query code is here)

            SELECT i,Block,
            Result =
            CASE WHEN (Block=1) THEN
            COALESCE(Status_History,Current_History)
            ELSE
            COALESCE(Status_History, LAG(Status_History) OVER (PARTITION BY Block ORDER BY i),LAG(Current_Status) OVER (PARTITION BY Block ORDER BY i)
            END
            FROM
            My_Query





            share|improve this answer



























              0














              It seems like you are falling back on the first non-null value of the previous record when a condition is not met. In theory this could be a coalesce result of the previous values and the current values looking for the first non-null in the desired order.



              With My_query as (My query code is here)

              SELECT i,Block,
              Result =
              CASE WHEN (Block=1) THEN
              COALESCE(Status_History,Current_History)
              ELSE
              COALESCE(Status_History, LAG(Status_History) OVER (PARTITION BY Block ORDER BY i),LAG(Current_Status) OVER (PARTITION BY Block ORDER BY i)
              END
              FROM
              My_Query





              share|improve this answer

























                0












                0








                0







                It seems like you are falling back on the first non-null value of the previous record when a condition is not met. In theory this could be a coalesce result of the previous values and the current values looking for the first non-null in the desired order.



                With My_query as (My query code is here)

                SELECT i,Block,
                Result =
                CASE WHEN (Block=1) THEN
                COALESCE(Status_History,Current_History)
                ELSE
                COALESCE(Status_History, LAG(Status_History) OVER (PARTITION BY Block ORDER BY i),LAG(Current_Status) OVER (PARTITION BY Block ORDER BY i)
                END
                FROM
                My_Query





                share|improve this answer













                It seems like you are falling back on the first non-null value of the previous record when a condition is not met. In theory this could be a coalesce result of the previous values and the current values looking for the first non-null in the desired order.



                With My_query as (My query code is here)

                SELECT i,Block,
                Result =
                CASE WHEN (Block=1) THEN
                COALESCE(Status_History,Current_History)
                ELSE
                COALESCE(Status_History, LAG(Status_History) OVER (PARTITION BY Block ORDER BY i),LAG(Current_Status) OVER (PARTITION BY Block ORDER BY i)
                END
                FROM
                My_Query






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Mar 26 at 14:42









                Ross BushRoss Bush

                11.2k22343




                11.2k22343



























                    draft saved

                    draft discarded
















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55320542%2fhow-to-integrate-while-loop-into-sql-query-repeating-last-result-in-the-column%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    SQL error code 1064 with creating Laravel foreign keysForeign key constraints: When to use ON UPDATE and ON DELETEDropping column with foreign key Laravel error: General error: 1025 Error on renameLaravel SQL Can't create tableLaravel Migration foreign key errorLaravel php artisan migrate:refresh giving a syntax errorSQLSTATE[42S01]: Base table or view already exists or Base table or view already exists: 1050 Tableerror in migrating laravel file to xampp serverSyntax error or access violation: 1064:syntax to use near 'unsigned not null, modelName varchar(191) not null, title varchar(191) not nLaravel cannot create new table field in mysqlLaravel 5.7:Last migration creates table but is not registered in the migration table

                    용인 삼성생명 블루밍스 목차 통계 역대 감독 선수단 응원단 경기장 같이 보기 외부 링크 둘러보기 메뉴samsungblueminx.comeh선수 명단용인 삼성생명 블루밍스용인 삼성생명 블루밍스ehsamsungblueminx.comeheheheh

                    155 수학 과학 기타 둘러보기 메뉴eh추가해eh문서를 완성해