High Scores in Abap: Complete Solution & Deep Dive Guide

two sets of brown Code Happy marquee lights

From Zero to Hero: Building a High Scores System in ABAP

Learn to manage a high score list in ABAP by building a component for a classic game. This guide covers retrieving the highest score, the last added score, and the top three scores using modern ABAP syntax, internal tables, sorting, and data manipulation techniques essential for any ABAP developer.

Ever felt that rush of seeing your initials at the top of an arcade machine? That simple list of names and numbers represents a core programming challenge: managing, sorting, and retrieving data from a collection. In the world of enterprise software with SAP, this isn't just about games; it's about processing millions of records, generating critical financial reports, and making data-driven decisions. The principles are exactly the same.

You might be staring at a requirement to rank sales data or find the most recent customer interactions and feel a bit lost. How do you efficiently handle large sets of data in memory? How do you pluck out the exact pieces of information you need without writing slow, convoluted code? This is a common pain point for developers new to the ABAP ecosystem.

In this comprehensive guide, we'll demystify these concepts. Using a fun and practical "High Scores" challenge from the exclusive kodikra.com learning curriculum, we will walk you through the fundamental ABAP skills for data manipulation. You will learn not just how to solve this specific problem, but how to apply these powerful techniques to any real-world business scenario you'll encounter as an SAP developer.


What Are We Building? The High Scores Component

The mission is to create an ABAP component (a class) that can manage a list of scores. This component needs to perform three specific tasks based on a given list of scores:

  • Find the Highest Score: From the entire list, identify and return the single top score.
  • Find the Last Added Score: Return the score that was most recently added to the list, regardless of its value.
  • Find the Top Three Scores: Return a new list containing the three highest scores, sorted from highest to lowest.

This challenge is a perfect vehicle for learning about ABAP's most powerful tool for handling datasets: the internal table. Let's dive into the core concepts before we write a single line of code.


Why Is Mastering ABAP Internal Tables So Crucial?

In the SAP universe, almost all data processing revolves around internal tables. Think of an internal table as a temporary, in-memory database table that your program can create and manipulate. When you fetch data from a database (like sales orders from table VBAK or material data from MARA), you load it into an internal table to work with it.

Understanding how to efficiently sort, read, modify, and loop through these tables is not just a "nice-to-have" skill—it is the absolute bedrock of ABAP development. Inefficient internal table operations can bring a multi-million dollar SAP system to its knees, while elegant, modern techniques can process vast amounts of data in the blink of an eye.

The High Scores module forces us to think about common business requirements:

  • Ranking: "Show me the top 10 products by revenue." (Our "Top Three Scores")
  • Extremes: "What was our highest single sale value last quarter?" (Our "Highest Score")
  • Sequence: "What is the status of the last order entered into the system?" (Our "Last Added Score")

By mastering this simple exercise, you are building the mental model for solving complex, large-scale business problems.


How to Implement the High Scores Logic in Modern ABAP

Let's get to the practical part. We will build a local class named lcl_high_scores to encapsulate our logic. This is a best practice in modern ABAP, promoting clean, reusable, and testable code. The class will have three public methods, one for each requirement.

The Complete ABAP Solution Code

Here is the full, well-commented code for our high scores component. We use modern ABAP syntax (available since ABAP 7.40), which is cleaner, more concise, and more powerful than older styles.


"&---------------------------------------------------------------------
"& Class lcl_high_scores DEFINITION
"&---------------------------------------------------------------------
"& This class manages a list of high scores, providing methods to
"& retrieve the highest, last, and top three scores.
"& This solution is part of the exclusive kodikra.com learning curriculum.
"&---------------------------------------------------------------------
CLASS lcl_high_scores DEFINITION.
  PUBLIC SECTION.
    TYPES:
      " Defines the structure for a single score entry
      BEGIN OF ty_score,
        player TYPE string,
        score  TYPE i,
      END OF ty_score.

      " Defines an internal table type to hold a list of scores
      tt_scores TYPE STANDARD TABLE OF ty_score WITH EMPTY KEY.

    METHODS:
      " Returns the single highest score from the list
      get_highest_score
        IMPORTING
          it_scores       TYPE tt_scores
        RETURNING
          VALUE(rv_score) TYPE i,

      " Returns the last score that was added to the list
      get_last_added_score
        IMPORTING
          it_scores       TYPE tt_scores
        RETURNING
          VALUE(rv_score) TYPE i,

      " Returns a list of the top three scores in descending order
      get_top_three_scores
        IMPORTING
          it_scores          TYPE tt_scores
        RETURNING
          VALUE(rt_top_scores) TYPE tt_scores.
ENDCLASS.


"&---------------------------------------------------------------------
"& Class lcl_high_scores IMPLEMENTATION
"&---------------------------------------------------------------------
"& Contains the logic for the high score management methods.
"&---------------------------------------------------------------------
CLASS lcl_high_scores IMPLEMENTATION.

  METHOD get_highest_score.
    " To find the highest score, we create a local copy to avoid
    " modifying the original table (a good practice).
    DATA lt_sorted_scores TYPE tt_scores.
    lt_sorted_scores = it_scores.

    " If the table is empty, we cannot find a highest score. Return 0.
    IF lt_sorted_scores IS INITIAL.
      rv_score = 0.
      RETURN.
    ENDIF.

    " Sort the table by score in descending order.
    " The highest score will now be at the very first position (index 1).
    SORT lt_sorted_scores BY score DESCENDING.

    " Read the first line of the sorted table.
    READ TABLE lt_sorted_scores INTO DATA(ls_highest_score) INDEX 1.

    " After a READ TABLE, sy-subrc = 0 means the read was successful.
    IF sy-subrc = 0.
      rv_score = ls_highest_score-score.
    ELSE.
      " This case is unlikely if we already checked for initial,
      " but it's robust to handle it.
      rv_score = 0.
    ENDIF.
  ENDMETHOD.


  METHOD get_last_added_score.
    " The "last added" score is simply the last entry in the internal table,
    " as APPEND adds new entries to the end.

    " Find the total number of lines in the table.
    DATA(lv_lines) = lines( it_scores ).

    " If the table is empty, there is no last score. Return 0.
    IF lv_lines = 0.
      rv_score = 0.
      RETURN.
    ENDIF.

    " Read the table at the last index.
    READ TABLE it_scores INTO DATA(ls_last_score) INDEX lv_lines.

    IF sy-subrc = 0.
      rv_score = ls_last_score-score.
    ELSE.
      rv_score = 0.
    ENDIF.
  ENDMETHOD.


  METHOD get_top_three_scores.
    " Similar to finding the highest score, we need to sort the list first.
    DATA lt_sorted_scores TYPE tt_scores.
    lt_sorted_scores = it_scores.

    " Sort the table by score in descending order.
    SORT lt_sorted_scores BY score DESCENDING.

    " Determine how many scores to retrieve. It's the smaller of 3 or
    " the actual number of scores available.
    DATA(lv_lines_total) = lines( lt_sorted_scores ).
    DATA(lv_lines_to_take) = nmin( val1 = 3 val2 = lv_lines_total ).

    " If there are scores to take, use a table expression (slicing)
    " to get the first N lines. This is a very efficient modern technique.
    IF lv_lines_to_take > 0.
      rt_top_scores = VALUE #( FOR i = 1 WHILE i <= lv_lines_to_take ( lt_sorted_scores[ i ] ) ).
    ENDIF.
    " If lv_lines_to_take is 0, the returning table rt_top_scores remains empty,
    " which is the correct behavior.
  ENDMETHOD.

ENDCLASS.

Detailed Code Walkthrough

Let's break down the logic of each method piece by piece.

1. get_highest_score Method

The goal is to find the single largest number in the list.

  • Defensive Copy: We start by copying the input table it_scores into a local variable lt_sorted_scores. This is crucial because ABAP passes standard internal tables by reference. If we sorted it_scores directly, we would change the original table in the calling program, which is an unexpected side effect.
  • Empty Check: We check if the table IS INITIAL. If it's empty, we can't find a score, so we immediately return 0.
  • The Core Logic: SORT: The most efficient way to find the maximum value is to sort the list. The statement SORT lt_sorted_scores BY score DESCENDING. rearranges the table so that the entry with the highest score is at the top (index 1).
  • Retrieval: READ TABLE: Once sorted, we know the highest score is in the first row. READ TABLE ... INDEX 1 is the most direct way to access it. We use an inline declaration DATA(ls_highest_score) to create a work area on the fly.
  • Safety Check: sy-subrc: After any read operation, we must check the system field sy-subrc. A value of 0 means the operation was successful. If it's non-zero, the read failed (which shouldn't happen here after our initial check, but it's a mandatory habit for robust code).

2. get_last_added_score Method

This is simpler. We need the score that was last put into the list, which corresponds to its position, not its value.

  • Find the End: The built-in function lines( it_scores ) gives us the total number of rows in the table. This number is also the index of the last row.
  • Empty Check: Again, we check if the number of lines is zero and return 0 if so.
  • Read by Index: We use READ TABLE ... INDEX lv_lines to directly access that final row and retrieve its score. The concept is identical to reading by index 1, but we target the end of the table instead of the beginning.

3. get_top_three_scores Method

This method combines sorting with a modern technique for extracting a subset of a table.

    ● Start (Receive score list)
    │
    ▼
  ┌───────────────────────────┐
  │ Create local copy of list │
  └────────────┬──────────────┘
               │
               ▼
  ┌───────────────────────────┐
  │ SORT copy by score DESC   │
  └────────────┬──────────────┘
               │
               ▼
  ◆  How many scores exist?
  │
  ├─> Less than 3? ───┐
  │                   │
  └─> 3 or more? ──┐  │
                    │  │
                    ▼  ▼
  ┌─────────────────┴───┐
  │ Take min(3, count)  │
  └─────────┬───────────┘
            │
            ▼
  ┌───────────────────────────┐
  │ Slice table [1 TO N]      │
  └────────────┬──────────────┘
               │
               ▼
    ● End (Return new list)
  • Sort First: Just like finding the single highest score, our first step is to SORT the list in DESCENDING order. Now the top three scores are conveniently located in rows 1, 2, and 3.
  • Handle Edge Cases: What if the list has fewer than three scores? We can't return three. The line DATA(lv_lines_to_take) = nmin( val1 = 3 val2 = lv_lines_total ). cleverly handles this. The nmin function returns the minimum of the two values, so if the table has only 2 entries, lv_lines_to_take will be 2.
  • Modern Slicing: The final line is the most modern piece of ABAP in this solution. rt_top_scores = VALUE #( FOR i = 1 WHILE i <= lv_lines_to_take ( lt_sorted_scores[ i ] ) ). is a powerful constructor expression.
    • VALUE #(): Creates a new internal table.
    • FOR i = 1 WHILE i <= lv_lines_to_take: It's like a compact LOOP that runs from index 1 up to the number of lines we need.
    • ( lt_sorted_scores[ i ] ): For each iteration, it takes the line at the current index i from our sorted table and adds it to the new table being constructed. This is called "slicing."

Where This Pattern Shines in Real SAP Scenarios

You might be thinking, "This is a neat academic exercise, but where would I use this at my job?" The answer is: everywhere.

  • Sales Reporting: A user asks for a report of the top 50 customers by sales volume for the last quarter. You would SELECT the sales data into an internal table, SORT it by volume descending, and then use the slicing technique to display the first 50 rows.
  • Inventory Management: To identify slow-moving items, you might query stock data, calculate the last movement date for each item, SORT by that date ascending, and take the top 100 to find the oldest stock.
  • HR and Payroll: When processing bonuses, you might need to find the 3 most recent performance reviews for an employee. You'd select the reviews into an internal table (which would likely already be sorted by date from the database), and read the last 3 entries using their indices.
  • Log Analysis: When debugging an issue, you often need to see the last 10 error messages logged by a program. You'd fetch the logs into an internal table and read the last 10 lines.

The core pattern of Fetch -> Sort -> Read/Slice is one of the most common and powerful workflows in all of ABAP programming.


Alternative Approaches & Performance Considerations

While our solution uses modern, efficient techniques, it's useful to understand other ways to solve the problem and why we chose our approach.

Alternative for Top Three: The Old-Fashioned LOOP

Before the modern slicing syntax, a developer would have used a LOOP with a counter:


" Old way to get top three
DATA lv_counter TYPE i.
LOOP AT lt_sorted_scores INTO DATA(ls_score).
  lv_counter = lv_counter + 1.
  IF lv_counter > 3.
    EXIT. " Exit the loop after the third entry
  ENDIF.
  APPEND ls_score TO rt_top_scores.
ENDLOOP.

Let's compare these two approaches.

    ▼ Modern Slicing ▼                  ▼ Traditional LOOP ▼
  ┌──────────────────────┐             ┌──────────────────────┐
  │ SORT table DESC      │             │ SORT table DESC      │
  └──────────┬───────────┘             └──────────┬───────────┘
             │                                    │
             ▼                                    ▼
  ┌──────────────────────┐             ┌──────────────────────┐
  │ Calculate N = min(3, lines) │      │ Initialize counter = 0 │
  └──────────┬───────────┘             └──────────┬───────────┘
             │                                    │
             ▼                                    ▼
  ┌──────────────────────┐             ┌──────────────────────┐
  │ rt_tab = VALUE #(...)│             │ LOOP AT sorted_tab   │
  │ (Single Expression)  │             │   counter++          │
  └──────────┬───────────┘             │   IF counter > 3 EXIT│
             │                         │   APPEND to rt_tab   │
             │                         │ ENDLOOP              │
             │                         └──────────────────────┘
             ▼
      ● End (Concise)                          ● End (Verbose)

Pros and Cons of Data Retrieval Methods

Method Pros Cons
SORT then READ INDEX 1 - Extremely fast and efficient for finding min/max.
- Very readable and clear intent.
- Modifies the table order (requires a copy for safety).
- Overhead of sorting is significant for very large tables if you only do it once.
Modern Slicing (Constructor Expression) - Highly expressive and concise.
- Often more performant than manual APPEND in a LOOP.
- Creates the final table in a single, clean statement.
- Syntax can be intimidating for beginners.
- Requires ABAP 7.40 or higher.
Traditional LOOP with EXIT - Works on all versions of ABAP.
- Logic is very explicit and easy to follow for simple cases.
- More verbose (more lines of code).
- Can be slightly less performant due to line-by-line processing and appends.
LOOP and Manual Comparison (No Sort) - Avoids the overhead of sorting the entire table. - Extremely complex and inefficient code to find top N items.
- Error-prone and very difficult to read/maintain. Almost never the right choice.

For our use case, the combination of SORT and then either READ TABLE or slicing is unequivocally the best practice. It provides the optimal balance of performance, readability, and modern syntax.


Frequently Asked Questions (FAQ)

What exactly is an internal table in ABAP?
An internal table is a dynamic data object that exists only during the runtime of an ABAP program. It's used to hold and process sets of data with an identical structure, much like a spreadsheet or a database table, but in the application's memory.
How do you sort an internal table in descending order?
You use the SORT statement with the DESCENDING addition. For example, to sort a table lt_data by a field named value, you would write: SORT lt_data BY value DESCENDING..
What's the difference between STANDARD, SORTED, and HASHED tables?
These are the three main types of internal tables. A STANDARD table (used in our solution) is accessed via index, has no unique key, and is the most flexible. A SORTED table is always kept sorted by its key, offering fast key-based reads. A HASHED table uses a hash algorithm for its key, providing the absolute fastest read time for a full key but can only be accessed by that key, not by index.
Can I get the top N scores dynamically?
Yes. In our get_top_three_scores method, the number 3 is hardcoded. You could easily change the method to accept an additional parameter, for example iv_count TYPE i, and then use that variable in the nmin function and the WHILE condition of the slicing expression instead of the literal 3.
Why is `sy-subrc` so important after a `READ TABLE` statement?
sy-subrc is a system field that indicates the success or failure of the preceding statement. For READ TABLE, a sy-subrc of 0 means a line was found and read successfully. A value of 4 means no line was found that matched the criteria (e.g., the index was out of bounds). Always checking it prevents your program from crashing or acting on invalid/empty data.
Is it better to sort the table every time I need the top scores?
It depends. If the data changes frequently and you need the most current ranking, then yes, sorting before retrieval is necessary. If the data is static and you need to perform many read operations, you might consider using a SORTED internal table type, which maintains its sort order automatically, albeit with a slight performance cost on insertions.
What are some common pitfalls when working with ABAP internal tables?
A major pitfall is modifying a table passed by reference when the calling program doesn't expect it (which is why we make a copy). Another is performing a LOOP inside another LOOP on very large tables, which can lead to catastrophic performance issues. Finally, forgetting to check sy-subrc after a READ can lead to unexpected errors when the program tries to use a work area that was never filled.

Conclusion: From Game Scores to Business Logic

We've successfully built a robust, efficient, and modern ABAP component for managing high scores. Along the way, we've explored the most fundamental concepts of ABAP development: the power of internal tables, the importance of sorting, and the elegance of modern syntax for data retrieval and manipulation.

The patterns you learned here—making defensive copies, sorting by a specific criterion, reading by index, and slicing tables—are not just for game logic. They are the daily tools you will use to build powerful reports, process complex business transactions, and write clean, maintainable code in the SAP ecosystem. By mastering these basics, you've laid a solid foundation for a successful career in ABAP development.

Disclaimer: The code examples in this article are written using modern ABAP syntax (version 7.40 and higher) and are intended for use in SAP S/4HANA or SAP Business Technology Platform (BTP) ABAP Environment systems.

Ready to tackle the next challenge and continue building your skills? Explore the full ABAP Learning Path on kodikra.com or dive deeper into the language with our complete ABAP programming guide.


Published by Kodikra — Your trusted Abap learning resource.