Cleaning Up Tables with Null Values Using SQL's max() Function

Understanding Null Values in SQL

As developers, we often encounter null values in our databases. These values can be frustrating to work with, especially when trying to clean up or analyze data.

In this article, we’ll explore a common problem involving null values and how to use the max() function to fill them in.

The Problem: Cleaning Up Tables with Null Values

We’re given a table with an ID column, a Number column, and a Type column. We want to clean up the table by filling in all empty rows within the first non-null value of each group (i.e., the group where the Type is ‘%’). This means that if we have multiple rows for the same ID but different Types, we only keep the one with the ‘%’ Type.

We’ll start by looking at an example of what this table might look like:

IDNumberType
151280%
A
251279%
B
350631%
A
B
C

And the desired output:

IDNumberType
151280%
151280A
251279%
251279B
350631%
350631A
350631B
350631C

Using lag() to Fill in Null Values

We’re given a code snippet that uses the lag() function to fill in null values:

select ID, number, type,
       case when number is not null then number 
         else lag(number) over (order by id) end as new_number
from tbl
order by ID;

This code works fine for records with only one Type besides ‘%’. However, it has a problem when there are multiple Types. For example, if we have an ID of 3 and two different Types (‘A’ and ‘B’), the lag() function will only use the value from the previous row where the Type is ‘A’, not the latest value.

The Solution: Using max() to Fill in Null Values

The answer to our problem lies in using the max() function. We can partition by ID to ensure that we’re always looking at the maximum value for each group:

select ID, number, type,
       max(number) over (partition by id) as new_number
from tbl
order by ID;

This code works because max() ignores null values. By partitioning by ID, we ensure that we’re only looking at the maximum value for each group.

Why It Works

So why does this solution work? The key insight is that max() returns the maximum value within a partition. When we partition by ID, each partition contains all rows with the same ID. For each ID, max() will return the highest non-null value. This means that even if there are multiple Types for an ID, max() will only consider the latest non-null value.

Example Use Case

Let’s go back to our original table:

IDNumberType
151280%
A
251279%
B
350631%
A
B
C

Using the max() function, we get:

IDNumberTypenew_number
151280%51280
151280A51280
251279%51279
251279B51279
350631%50631
350631A50631
350631B50631
350631C50631

As we can see, the max() function has successfully filled in all null values.

Conclusion

In this article, we explored a common problem involving null values and how to use the max() function to fill them in. By partitioning by ID, we ensure that we’re only looking at the maximum value for each group, ignoring any null values. This solution works because max() returns the highest non-null value within a partition, allowing us to efficiently clean up our table.

Note: Remember to adjust the column names and database schema according to your needs.


Last modified on 2025-02-04