Skip to content

Decoding datelist ints 🔓

Tip

Solution to the following problem:

Result Set

Regardless of the database, the result set should look like:

active_date user_1 user_2 user_3 user_4 user_5 user_6
2024-05-03 0 1 0 0 0 0
2024-05-04 0 1 0 0 0 1
2024-05-05 0 0 1 0 1 1
2024-05-06 0 1 1 0 1 1
2024-05-07 0 1 0 0 1 0
2024-05-08 0 0 0 0 0 1
2024-05-09 0 0 0 1 1 0
2024-05-10 0 0 0 0 0 1
2024-05-11 0 0 0 0 1 0
2024-05-12 1 1 0 1 0 1
2024-05-13 0 0 0 0 1 1
2024-05-14 0 1 0 1 1 1
2024-05-15 0 0 0 0 0 0
2024-05-16 0 0 0 1 1 1
2024-05-17 0 0 0 0 0 0
2024-05-18 0 0 0 0 1 1
2024-05-19 0 1 1 0 1 1
2024-05-20 1 0 0 1 1 0
2024-05-21 1 0 0 0 0 1
2024-05-22 1 0 0 0 0 0
2024-05-23 1 1 0 0 0 0
2024-05-24 0 1 0 1 0 0
2024-05-25 0 0 1 0 0 1
2024-05-26 0 0 1 1 1 1
2024-05-27 0 0 1 1 0 1
2024-05-28 0 1 1 0 1 1
2024-05-29 0 1 1 0 0 0
2024-05-30 0 0 0 0 1 1
2024-05-31 0 0 0 0 1 1
2024-06-01 0 0 0 0 0 1
Expand for the DDL
solution(active_date, user_1, user_2, user_3, user_4, user_5, user_6) as (
    values
        ('2024-05-03'::date, 0, 1, 0, 0, 0, 0),
        ('2024-05-04'::date, 0, 1, 0, 0, 0, 1),
        ('2024-05-05'::date, 0, 0, 1, 0, 1, 1),
        ('2024-05-06'::date, 0, 1, 1, 0, 1, 1),
        ('2024-05-07'::date, 0, 1, 0, 0, 1, 0),
        ('2024-05-08'::date, 0, 0, 0, 0, 0, 1),
        ('2024-05-09'::date, 0, 0, 0, 1, 1, 0),
        ('2024-05-10'::date, 0, 0, 0, 0, 0, 1),
        ('2024-05-11'::date, 0, 0, 0, 0, 1, 0),
        ('2024-05-12'::date, 1, 1, 0, 1, 0, 1),
        ('2024-05-13'::date, 0, 0, 0, 0, 1, 1),
        ('2024-05-14'::date, 0, 1, 0, 1, 1, 1),
        ('2024-05-15'::date, 0, 0, 0, 0, 0, 0),
        ('2024-05-16'::date, 0, 0, 0, 1, 1, 1),
        ('2024-05-17'::date, 0, 0, 0, 0, 0, 0),
        ('2024-05-18'::date, 0, 0, 0, 0, 1, 1),
        ('2024-05-19'::date, 0, 1, 1, 0, 1, 1),
        ('2024-05-20'::date, 1, 0, 0, 1, 1, 0),
        ('2024-05-21'::date, 1, 0, 0, 0, 0, 1),
        ('2024-05-22'::date, 1, 0, 0, 0, 0, 0),
        ('2024-05-23'::date, 1, 1, 0, 0, 0, 0),
        ('2024-05-24'::date, 0, 1, 0, 1, 0, 0),
        ('2024-05-25'::date, 0, 0, 1, 0, 0, 1),
        ('2024-05-26'::date, 0, 0, 1, 1, 1, 1),
        ('2024-05-27'::date, 0, 0, 1, 1, 0, 1),
        ('2024-05-28'::date, 0, 1, 1, 0, 1, 1),
        ('2024-05-29'::date, 0, 1, 1, 0, 0, 0),
        ('2024-05-30'::date, 0, 0, 0, 0, 1, 1),
        ('2024-05-31'::date, 0, 0, 0, 0, 1, 1),
        ('2024-06-01'::date, 0, 0, 0, 0, 0, 1)
)

Solution

Some SQL solutions per database are provided below.

DuckDB

with recursive

axis(active_date, max_, step) as (
        select
            (select last_update from user_history limit 1),
            (select max(log2(activity_history)) from user_history),
            1
    union all
        select active_date - 1, max_, step + 1
        from axis
        where step < max_
),

decoded as (
    select
        user_history.user_id,
        axis.active_date,
        (activity_history & power(2, axis.step - 1)::int > 0)::int as active_flag
    from axis
        cross join user_history
)

pivot decoded
on ('user_' || user_id)
using any_value(active_flag)
order by active_date