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;
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!
add a comment |
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!
add a comment |
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!
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!
edited Mar 27 at 17:56
Regressionist
asked Mar 24 at 3:43
RegressionistRegressionist
63
63
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
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
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 usingMAX(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, andUNIONstatements 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
add a comment |
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
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
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 usingMAX(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, andUNIONstatements 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
add a comment |
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
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 usingMAX(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, andUNIONstatements 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
add a comment |
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
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
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 usingMAX(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, andUNIONstatements 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
add a comment |
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 usingMAX(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, andUNIONstatements 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
add a comment |
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
add a comment |
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
add a comment |
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
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
answered Mar 26 at 14:42
Ross BushRoss Bush
11.2k22343
11.2k22343
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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