SQL Server – Adding ‘Last Time Occurred’ Flag Column

greatest-n-per-groupsql server

I need to add a column into a table that contains 3 columns:

  1. GroupKey – Shows the number of an item.
  2. Status – the number of the status that the group was according the insert date. The status number can be changed back and forward several times.
  3. Insert date – the time & date that the status changed.

This 3 columns never change. its like a "log" table , rows can be only added and not deleted or changend

The fourth column (calculated Column) that I need is a flag column that will show if the status was the last time the status has been changed based on the insert_date.

If it is the last status then show 1, else show 0. I hope I explained this well enough. Here is an example:

This is the table.

Best Answer

Another way would be to have a computed column. But the values of this column depend not only on the values of the other columns in the same row but from other rows as well, so this isn't allowed in SQL-Server (and not in any other DBMS I know).

You can still have though such a computed column in a view, with:

create view vlog as
  select log.*,
         IsLastTimeAccured =
           case when inserted_date = 
                     max(inserted_date) over (partition by GroupKey, "Status")
                then 1 else 0
           end 
  from log ;

Test at SQLfiddle. This way, you don't really store any value at all but they have to be actually calculated every time you need them. This may not be as efficient as having it stored as an actual column (and keeping it consistent with a trigger as in @PaulWhite's answer.) You also can't index it. But the rows will not have to be modified when new inserts come and no redundant data is stored.

As pointed by @MikaelEriksson, if you are in SQL-Server 2012+, you can use the LAST_VALUE() or the FIRST_VALUE() window function instead of MAX(), for improved performance. With a supporting index on (GroupKey, [Status], inserted_date desc), the case expression would become:

   case when inserted_date = first_value(inserted_date) over
                               (partition by GroupKey, [Status]
                                order by inserted_date desc
                                rows between unbounded preceding and current row)
        then 1
        else 0
   end