How To Give a Condition To Data Row based on First and Next Data?
Hello my Friends,
I have a question, I have a data like this
.png)
And I want to create a display like this, which I can put a status column beside the Item Column
The status become new, if there's no previous item, and if there's a same item after the first one, the status become Old
.png)
Does anyone could help me ?
I need to display it without subquery if possible
Thank You
Best Regards,
Steven Henry
Comments
I'm not sure this is the answer you're looking for, but I would loop through the result set and store the data in a local array and then loop through the array and output the data with the calculated column set as you wish. The array would allow you to loop through each ID to find the latest to mark as new. This is an ObjectScript approach along with SQL. I wonder if you could just re-save the data back to the table once calculated so you can still project it as needed to other systems.
Suggestion:
you crate your own stored procedure to decide during SELECT
example:
/// Return NEW for first occurance of item /// otherwise return OLDClass User.ItemStat Extends%RegisteredObject
{
ClassMethod NewOld(item As%String = "") As%String [ SqlProc ]
{
if item=""quit"?"if$d(^||list(item)) quit"OLD"if$i(^||list(item)) quit"NEW"
}
}How to use it:
SELECT *, ItemStat_NewOld(item) asStatusFROM items orderby2Result:
ID date item Status
109/13/1932 A NEW204/06/1933DNEW1006/15/1940 A OLD
411/26/1940 A OLD
602/19/1956 B NEW804/22/1957D OLD
705/01/1959D OLD
906/29/1961 ?
307/04/1992 B OLD
512/08/2020D OLD
Hy Robert, thank you for your help
but can I use Query without store procedure ?
Thank you
Steve Henry
If available anyhow any SQL or TSQL is slower
Hi,
Using COS is pretty simple. As you loop the global with $o() simply put the ID value in an array or local global at the last line before going into the loop for the next id. Then for each loop, if $d(array(id)) it means is OLD, otherwise is NEW.
Right?
Hi everyone,
That stored procedure solution looks great, and may work, but I'd just like to point out that you have no control over what order the rows are in when the method is called. That's going to be decided by the compiler.
If you've done "ORDER BY Date DESC" then it could build a temporary index by date and then run through that to extract the output, so row 4 would be processed first and the call to the method will return "New" instead of "Old".
Putting in the required order in the query might work, but even then, you have no certainty what the compiler will do. You either need a subquery, or calculate the column outside of SQL when you pull the rows (in the right order).
Regards,
Mike
💡 This question is considered a Key Question. More details here.
Hey Steve, you said 'no subqueries,' but I figured Common Table Expressions with window functions were fair game, right? 😉
This is just a shot based on your example data. Not entirely sure I nailed your explanation about 'previous' and 'next'? 🤔
Maybe this will help:
WITH RankedEntries AS
(
SELECT
TheNO,
TheID,
TheDate,
Item,
ROW_NUMBER() OVER (PARTITION BY TheID, Item ORDER BY TheDate ASC) AS ItemRank
FROM MultipleEntries
)
SELECT
TheNO,
TheID,
TheDate,
Item,
CASE
WHEN ItemRank = 1 THEN 'new'
ELSE 'old'
END AS Status
FROM RankedEntries
ORDER BY TheNO;
Andreas
Dar Andreas,
thanks for your help
it works for me :)
Thank you