| Country | Contributions | Between | Climbers | Crags | Summits | Climbs | Ascents | |
|---|---|---|---|---|---|---|---|---|
| 1 | USA | 1526 | 20th November 2025 – 5th November 2026 | 48 | 20 | 0 | 88 | 98 |
| 2 | Australia | 767 | 28th September 2025 – 29th June 2026 | 6 | 38 | 0 | 61 | 33 |
| 3 | United Kingdom | 625 | 19th November 2025 – 4th November 2026 | 34 | 14 | 0 | 24 | 49 |
| 4 | Switzerland | 308 | 24th January 2026 – 4th November 2026 | 6 | 3 | 0 | 14 | 38 |
| 5 | France | 300 | 6th January 2026 – 4th November 2026 | 15 | 3 | 0 | 12 | 34 |
| 6 | Austria | 210 | 12th November 2025 – 23rd June 2026 | 5 | 2 | 0 | 8 | 22 |
| 7 | Italy | 163 | 19th November 2025 – 2nd November 2026 | 9 | 3 | 0 | 12 | 12 |
| 8 | Pakistan | 118 | 11th April 2026 – 27th April 2026 | 0 | 0 | 0 | 1 | 7 |
| 9 | Spain | 105 | 20th February 2026 – 17th May 2026 | 5 | 0 | 0 | 10 | 11 |
| 10 | Germany | 103 | 3rd February 2026 – 26th June 2026 | 7 | 0 | 0 | 7 | 10 |
| Date | Time | User | Type | Name | Attribute | ||
|---|---|---|---|---|---|---|---|
| 4861 | 24th March 2026 | 01:46:43 UTC | ben_sandi | list | Youngest Ascents (with date ranges) | list_description | |
|
Before
Main list here: [https://climbing-history.org/list/57/youngest-ascents](https://climbing-history.org/list/57/youngest-ascents)
The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers *maximum* age of ascent. Ideally we want to source the exact dates for the ascents listed here.
After
Main list here: [https://climbing-history.org/list/57/youngest-ascents](https://climbing-history.org/list/57/youngest-ascents)
The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers **maximum** age of ascent. Ideally we want to source the exact dates for the ascents listed here.
Diff
--- before
|
|||||||
| 4862 | 24th March 2026 | 01:45:27 UTC | ben_sandi | list | Youngest Ascents (with date ranges) | list_definition | |
|
Before
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by
a.ascent_dt_end - c.date_of_birth_start asc
,a.ascent_dt_start - c.date_of_birth_end asc
,a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,a.ascent_dt_start - c.date_of_birth_end as min_age_in_days_at_ascent
,a.ascent_dt_end - c.date_of_birth_start as max_age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer as min_age_in_years_at_ascent
,extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_start is not null
and a.ascent_dt_end is not null
and ast.ascent_successful = true
), youngest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
y.grade
,'<a href="/climber/' || y.climber_id::varchar || '">' || y.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || y.climb_id::varchar || '">' || y.climb_name || '</a>' as "Climb"
,y.max_age_in_days_at_ascent as "Maximum possible age (days)"
,case
when y.min_age_in_days_at_ascent = y.max_age_in_days_at_ascent then
y.min_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_start - (y.date_of_birth_end + make_interval(years => y.min_age_in_years_at_ascent))) ||
' days'
else
y.min_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_start - (y.date_of_birth_end + make_interval(years => y.min_age_in_years_at_ascent))) ||
' days to ' ||
y.max_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_end - (y.date_of_birth_start + make_interval(years => y.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when y.min_age_in_days_at_ascent = y.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
youngest y
where
case
when y.grade_system_id = 1 and y.order_on >= 13 then 1
when y.grade_system_id = 2 and y.order_on >= 60 then 1
when y.grade_system_id = 3 and y.order_on >= 37 then 1
else 0
end = 1
and y.climb_type_id in (1,2,3)
order by
y.grade_system_id
,y.order_on
After
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by
a.ascent_dt_end - c.date_of_birth_start asc nulls last
,a.ascent_dt_start - c.date_of_birth_end asc nulls last
,a.ascent_dt_start asc nulls last
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,case
when a.ascent_dt_start is not null then a.ascent_dt_start - c.date_of_birth_end
else null
end as min_age_in_days_at_ascent
,a.ascent_dt_end - c.date_of_birth_start as max_age_in_days_at_ascent
,case
when a.ascent_dt_start is not null then extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer
else null
end as min_age_in_years_at_ascent
,extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_end is not null
and ast.ascent_successful = true
), youngest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
y.grade
,'<a href="/climber/' || y.climber_id::varchar || '">' || y.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || y.climb_id::varchar || '">' || y.climb_name || '</a>' as "Climb"
,y.max_age_in_days_at_ascent as "Maximum possible age (days)"
,case
when y.ascent_dt_start is null then
'n/a to ' ||
y.max_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_end - (y.date_of_birth_start + make_interval(years => y.max_age_in_years_at_ascent))) ||
' days'
when y.min_age_in_days_at_ascent = y.max_age_in_days_at_ascent then
y.min_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_start - (y.date_of_birth_end + make_interval(years => y.min_age_in_years_at_ascent))) ||
' days'
else
y.min_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_start - (y.date_of_birth_end + make_interval(years => y.min_age_in_years_at_ascent))) ||
' days to ' ||
y.max_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_end - (y.date_of_birth_start + make_interval(years => y.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when y.ascent_dt_start is null then '✓'
when y.min_age_in_days_at_ascent = y.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
youngest y
where
case
when y.grade_system_id = 1 and y.order_on >= 13 then 1
when y.grade_system_id = 2 and y.order_on >= 60 then 1
when y.grade_system_id = 3 and y.order_on >= 37 then 1
else 0
end = 1
and y.climb_type_id in (1,2,3)
order by
y.grade_system_id
,y.order_on
Diff
--- before
|
|||||||
| 4863 | 24th March 2026 | 01:39:26 UTC | ben_sandi | list | Youngest Ascents (with date ranges) | list_definition | |
|
Before
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by a.ascent_dt_start - c.date_of_birth_end asc, a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,a.ascent_dt_start - c.date_of_birth_end as min_age_in_days_at_ascent
,a.ascent_dt_end - c.date_of_birth_start as max_age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer as min_age_in_years_at_ascent
,extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_start is not null
and a.ascent_dt_end is not null
and ast.ascent_successful = true
), youngest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
y.grade
,'<a href="/climber/' || y.climber_id::varchar || '">' || y.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || y.climb_id::varchar || '">' || y.climb_name || '</a>' as "Climb"
,y.min_age_in_days_at_ascent as "Minimum age (days)"
,case
when y.min_age_in_days_at_ascent = y.max_age_in_days_at_ascent then
y.min_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_start - (y.date_of_birth_end + make_interval(years => y.min_age_in_years_at_ascent))) ||
' days'
else
y.min_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_start - (y.date_of_birth_end + make_interval(years => y.min_age_in_years_at_ascent))) ||
' days to ' ||
y.max_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_end - (y.date_of_birth_start + make_interval(years => y.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when y.min_age_in_days_at_ascent = y.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
youngest y
where
case
when y.grade_system_id = 1 and y.order_on >= 13 then 1
when y.grade_system_id = 2 and y.order_on >= 60 then 1
when y.grade_system_id = 3 and y.order_on >= 37 then 1
else 0
end = 1
and y.climb_type_id in (1,2,3)
order by
y.grade_system_id
,y.order_on
After
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by
a.ascent_dt_end - c.date_of_birth_start asc
,a.ascent_dt_start - c.date_of_birth_end asc
,a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,a.ascent_dt_start - c.date_of_birth_end as min_age_in_days_at_ascent
,a.ascent_dt_end - c.date_of_birth_start as max_age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer as min_age_in_years_at_ascent
,extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_start is not null
and a.ascent_dt_end is not null
and ast.ascent_successful = true
), youngest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
y.grade
,'<a href="/climber/' || y.climber_id::varchar || '">' || y.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || y.climb_id::varchar || '">' || y.climb_name || '</a>' as "Climb"
,y.max_age_in_days_at_ascent as "Maximum possible age (days)"
,case
when y.min_age_in_days_at_ascent = y.max_age_in_days_at_ascent then
y.min_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_start - (y.date_of_birth_end + make_interval(years => y.min_age_in_years_at_ascent))) ||
' days'
else
y.min_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_start - (y.date_of_birth_end + make_interval(years => y.min_age_in_years_at_ascent))) ||
' days to ' ||
y.max_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_end - (y.date_of_birth_start + make_interval(years => y.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when y.min_age_in_days_at_ascent = y.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
youngest y
where
case
when y.grade_system_id = 1 and y.order_on >= 13 then 1
when y.grade_system_id = 2 and y.order_on >= 60 then 1
when y.grade_system_id = 3 and y.order_on >= 37 then 1
else 0
end = 1
and y.climb_type_id in (1,2,3)
order by
y.grade_system_id
,y.order_on
Diff
--- before
|
|||||||
| 4864 | 24th March 2026 | 01:35:10 UTC | ben_sandi | list | Youngest Ascents (with date ranges) | list_definition | |
|
Before
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by a.ascent_dt_end - c.date_of_birth_start asc, a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,a.ascent_dt_start - c.date_of_birth_end as min_age_in_days_at_ascent
,a.ascent_dt_end - c.date_of_birth_start as max_age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer as min_age_in_years_at_ascent
,extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_start is not null
and a.ascent_dt_end is not null
and ast.ascent_successful = true
), oldest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
o.grade
,'<a href="/climber/' || o.climber_id::varchar || '">' || o.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || o.climb_id::varchar || '">' || o.climb_name || '</a>' as "Climb"
,o.min_age_in_days_at_ascent as "Minimum age (days)"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days'
else
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days to ' ||
o.max_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_end - (o.date_of_birth_start + make_interval(years => o.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
oldest o
where
case
when o.grade_system_id = 1 and o.order_on >= 13 then 1
when o.grade_system_id = 2 and o.order_on >= 60 then 1
when o.grade_system_id = 3 and o.order_on >= 37 then 1
else 0
end = 1
and o.climb_type_id in (1,2,3)
order by
o.grade_system_id
,o.order_on
After
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by a.ascent_dt_start - c.date_of_birth_end asc, a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,a.ascent_dt_start - c.date_of_birth_end as min_age_in_days_at_ascent
,a.ascent_dt_end - c.date_of_birth_start as max_age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer as min_age_in_years_at_ascent
,extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_start is not null
and a.ascent_dt_end is not null
and ast.ascent_successful = true
), youngest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
y.grade
,'<a href="/climber/' || y.climber_id::varchar || '">' || y.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || y.climb_id::varchar || '">' || y.climb_name || '</a>' as "Climb"
,y.min_age_in_days_at_ascent as "Minimum age (days)"
,case
when y.min_age_in_days_at_ascent = y.max_age_in_days_at_ascent then
y.min_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_start - (y.date_of_birth_end + make_interval(years => y.min_age_in_years_at_ascent))) ||
' days'
else
y.min_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_start - (y.date_of_birth_end + make_interval(years => y.min_age_in_years_at_ascent))) ||
' days to ' ||
y.max_age_in_years_at_ascent || ' years ' ||
extract(days from y.ascent_dt_end - (y.date_of_birth_start + make_interval(years => y.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when y.min_age_in_days_at_ascent = y.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
youngest y
where
case
when y.grade_system_id = 1 and y.order_on >= 13 then 1
when y.grade_system_id = 2 and y.order_on >= 60 then 1
when y.grade_system_id = 3 and y.order_on >= 37 then 1
else 0
end = 1
and y.climb_type_id in (1,2,3)
order by
y.grade_system_id
,y.order_on
Diff
--- before
|
|||||||
| 4865 | 24th March 2026 | 01:32:42 UTC | ben_sandi | list | Youngest Ascents (with date ranges) | list_definition | |
|
Before
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by a.ascent_dt_end - c.date_of_birth_start asc, a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,a.ascent_dt_start - c.date_of_birth_end as min_age_in_days_at_ascent
,a.ascent_dt_end - c.date_of_birth_start as max_age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer as min_age_in_years_at_ascent
,extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_start is not null
and a.ascent_dt_end is not null
and ast.ascent_successful = true
), oldest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
o.grade
,'<a href="/climber/' || o.climber_id::varchar || '">' || o.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || o.climb_id::varchar || '">' || o.climb_name || '</a>' as "Climb"
,o.min_age_in_days_at_ascent as "Maximum age (days)"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days'
else
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days to ' ||
o.max_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_end - (o.date_of_birth_start + make_interval(years => o.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
oldest o
where
case
when o.grade_system_id = 1 and o.order_on >= 13 then 1
when o.grade_system_id = 2 and o.order_on >= 60 then 1
when o.grade_system_id = 3 and o.order_on >= 37 then 1
else 0
end = 1
and o.climb_type_id in (1,2,3)
order by
o.grade_system_id
,o.order_on
After
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by a.ascent_dt_end - c.date_of_birth_start asc, a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,a.ascent_dt_start - c.date_of_birth_end as min_age_in_days_at_ascent
,a.ascent_dt_end - c.date_of_birth_start as max_age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer as min_age_in_years_at_ascent
,extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_start is not null
and a.ascent_dt_end is not null
and ast.ascent_successful = true
), oldest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
o.grade
,'<a href="/climber/' || o.climber_id::varchar || '">' || o.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || o.climb_id::varchar || '">' || o.climb_name || '</a>' as "Climb"
,o.min_age_in_days_at_ascent as "Minimum age (days)"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days'
else
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days to ' ||
o.max_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_end - (o.date_of_birth_start + make_interval(years => o.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
oldest o
where
case
when o.grade_system_id = 1 and o.order_on >= 13 then 1
when o.grade_system_id = 2 and o.order_on >= 60 then 1
when o.grade_system_id = 3 and o.order_on >= 37 then 1
else 0
end = 1
and o.climb_type_id in (1,2,3)
order by
o.grade_system_id
,o.order_on
Diff
--- before
|
|||||||
| 4866 | 24th March 2026 | 01:30:10 UTC | ben_sandi | list | Youngest Ascents (with date ranges) | list_definition | |
|
Before
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by a.ascent_dt_end - c.date_of_birth_start asc, a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,a.ascent_dt_start - c.date_of_birth_end as min_age_in_days_at_ascent
,a.ascent_dt_end - c.date_of_birth_start as max_age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer as min_age_in_years_at_ascent
,extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_start is not null
and a.ascent_dt_end is not null
and ast.ascent_successful = true
), oldest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
o.grade
,'<a href="/climber/' || o.climber_id::varchar || '">' || o.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || o.climb_id::varchar || '">' || o.climb_name || '</a>' as "Climb"
,o.min_age_in_days_at_ascent as "Minimum age (days)"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days'
else
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days to ' ||
o.max_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_end - (o.date_of_birth_start + make_interval(years => o.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
oldest o
where
case
when o.grade_system_id = 1 and o.order_on >= 13 then 1
when o.grade_system_id = 2 and o.order_on >= 60 then 1
when o.grade_system_id = 3 and o.order_on >= 37 then 1
else 0
end = 1
and o.climb_type_id in (1,2,3)
order by
o.grade_system_id
,o.order_on
After
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by a.ascent_dt_end - c.date_of_birth_start asc, a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,a.ascent_dt_start - c.date_of_birth_end as min_age_in_days_at_ascent
,a.ascent_dt_end - c.date_of_birth_start as max_age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer as min_age_in_years_at_ascent
,extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_start is not null
and a.ascent_dt_end is not null
and ast.ascent_successful = true
), oldest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
o.grade
,'<a href="/climber/' || o.climber_id::varchar || '">' || o.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || o.climb_id::varchar || '">' || o.climb_name || '</a>' as "Climb"
,o.min_age_in_days_at_ascent as "Maximum age (days)"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days'
else
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days to ' ||
o.max_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_end - (o.date_of_birth_start + make_interval(years => o.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
oldest o
where
case
when o.grade_system_id = 1 and o.order_on >= 13 then 1
when o.grade_system_id = 2 and o.order_on >= 60 then 1
when o.grade_system_id = 3 and o.order_on >= 37 then 1
else 0
end = 1
and o.climb_type_id in (1,2,3)
order by
o.grade_system_id
,o.order_on
Diff
--- before
|
|||||||
| 4867 | 24th March 2026 | 01:28:47 UTC | ben_sandi | list | Oldest Ascents (with date ranges) | list_definition | |
|
Before
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by a.ascent_dt_start - c.date_of_birth_end desc, a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,a.ascent_dt_start - c.date_of_birth_end as min_age_in_days_at_ascent
,a.ascent_dt_end - c.date_of_birth_start as max_age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer as min_age_in_years_at_ascent
,extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_start is not null
and a.ascent_dt_end is not null
and ast.ascent_successful = true
), oldest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
o.grade
,'<a href="/climber/' || o.climber_id::varchar || '">' || o.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || o.climb_id::varchar || '">' || o.climb_name || '</a>' as "Climb"
,o.min_age_in_days_at_ascent as "Minimum age (days)"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days'
else
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days to ' ||
o.max_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_end - (o.date_of_birth_start + make_interval(years => o.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
oldest o
where
case
when o.grade_system_id = 1 and o.order_on >= 13 then 1
when o.grade_system_id = 2 and o.order_on >= 60 then 1
when o.grade_system_id = 3 and o.order_on >= 37 then 1
else 0
end = 1
and o.climb_type_id in (1,2,3)
order by
o.grade_system_id
,o.order_on
After
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by a.ascent_dt_start - c.date_of_birth_end desc, a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,a.ascent_dt_start - c.date_of_birth_end as min_age_in_days_at_ascent
,case
when a.ascent_dt_end is not null then a.ascent_dt_end - c.date_of_birth_start
else null
end as max_age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer as min_age_in_years_at_ascent
,case
when a.ascent_dt_end is not null then extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer
else null
end as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_start is not null
and ast.ascent_successful = true
), oldest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
o.grade
,'<a href="/climber/' || o.climber_id::varchar || '">' || o.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || o.climb_id::varchar || '">' || o.climb_name || '</a>' as "Climb"
,o.min_age_in_days_at_ascent as "Minimum age (days)"
,case
when o.ascent_dt_end is null then
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days to n/a'
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days'
else
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days to ' ||
o.max_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_end - (o.date_of_birth_start + make_interval(years => o.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when o.ascent_dt_end is null then '✓'
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
oldest o
where
case
when o.grade_system_id = 1 and o.order_on >= 13 then 1
when o.grade_system_id = 2 and o.order_on >= 60 then 1
when o.grade_system_id = 3 and o.order_on >= 37 then 1
else 0
end = 1
and o.climb_type_id in (1,2,3)
order by
o.grade_system_id
,o.order_on
Diff
--- before
|
|||||||
| 4868 | 24th March 2026 | 01:09:10 UTC | ben_sandi | list | Oldest Ascents | list_definition | |
|
Before
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start as date_of_birth
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start = c.date_of_birth_end
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by a.ascent_dt_start - c.date_of_birth desc, a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,c.date_of_birth
,a.ascent_dt_start - c.date_of_birth as age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth))::integer as age_in_years_at_ascent
,age(a.ascent_dt_start, c.date_of_birth) as age_interval_at_ascent
,a.ascent_id
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
where
a.ascent_dt_start = a.ascent_dt_end
), oldest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
o.grade
,'<a href="/climber/' || o.climber_id::varchar || '">' || o.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || o.climb_id::varchar || '">' || o.climb_name || '</a>' as "Climb"
,o.age_in_days_at_ascent as "Age (Days)"
,o.age_in_years_at_ascent || ' years ' || extract(days from o.ascent_dt_start - (o.date_of_birth + make_interval(years => o.age_in_years_at_ascent))) || ' days' as "Age"
from
oldest o
where
case
when grade_system_id = 1 and order_on >= 13 then 1
when grade_system_id = 2 and order_on >= 60 then 1
when grade_system_id = 3 and order_on >= 37 then 1
else 0
end = 1
and climb_type_id in (1,2,3)
order by
grade_system_id
,order_on
After
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start as date_of_birth
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start = c.date_of_birth_end
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by a.ascent_dt_start - c.date_of_birth desc, a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,c.date_of_birth
,a.ascent_dt_start - c.date_of_birth as age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth))::integer as age_in_years_at_ascent
,age(a.ascent_dt_start, c.date_of_birth) as age_interval_at_ascent
,a.ascent_id
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_start = a.ascent_dt_end
and ast.ascent_successful = true
), oldest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
o.grade
,'<a href="/climber/' || o.climber_id::varchar || '">' || o.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || o.climb_id::varchar || '">' || o.climb_name || '</a>' as "Climb"
,o.age_in_days_at_ascent as "Age (Days)"
,o.age_in_years_at_ascent || ' years ' || extract(days from o.ascent_dt_start - (o.date_of_birth + make_interval(years => o.age_in_years_at_ascent))) || ' days' as "Age"
from
oldest o
where
case
when grade_system_id = 1 and order_on >= 13 then 1
when grade_system_id = 2 and order_on >= 60 then 1
when grade_system_id = 3 and order_on >= 37 then 1
else 0
end = 1
and climb_type_id in (1,2,3)
order by
grade_system_id
,order_on
Diff
--- before
|
|||||||
| 4869 | 24th March 2026 | 01:07:16 UTC | ben_sandi | list | Youngest Ascents | list_definition | |
|
Before
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start as date_of_birth
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start = c.date_of_birth_end
), ascents_with_ages as (
select
row_number() over (partition by g.grade_id order by a.ascent_dt_start - c.date_of_birth asc, a.ascent_dt_start asc) as row_number,
c.climber_id,
c.climber_name,
cl.climb_id,
cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,c.date_of_birth
,a.ascent_dt_start - c.date_of_birth as age_in_days_at_ascent
,EXTRACT(YEAR FROM age(a.ascent_dt_start, c.date_of_birth))::integer AS age_in_years_at_ascent
,age(a.ascent_dt_start, c.date_of_birth) as age_interval_at_ascent
,a.ascent_id
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
where
a.ascent_dt_start = a.ascent_dt_end
), youngest as (
select *
from ascents_with_ages
where row_number = 1
)
select
y.grade
,'<a href="/climber/' || y.climber_id::varchar || '">' || y.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || y.climb_id::varchar || '">' || y.climb_name || '</a>' as "Climb"
,y.age_in_days_at_ascent as "Age (Days)"
,y.age_in_years_at_ascent || ' years ' || extract(days FROM y.ascent_dt_start - (y.date_of_birth + make_interval(years => y.age_in_years_at_ascent))) || ' days' AS "Age"
from
youngest y
where
case
when grade_system_id = 1 and order_on >= 13 then 1 -- sport
when grade_system_id = 2 and order_on >= 60 then 1 -- trad
when grade_system_id = 3 and order_on >= 37 then 1 -- boulder
else 0
end = 1
and climb_type_id in (1,2,3)
order by
grade_system_id
,order_on
After
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start as date_of_birth
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start = c.date_of_birth_end
), ascents_with_ages as (
select
row_number() over (partition by g.grade_id order by a.ascent_dt_start - c.date_of_birth asc, a.ascent_dt_start asc) as row_number,
c.climber_id,
c.climber_name,
cl.climb_id,
cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,c.date_of_birth
,a.ascent_dt_start - c.date_of_birth as age_in_days_at_ascent
,EXTRACT(YEAR FROM age(a.ascent_dt_start, c.date_of_birth))::integer AS age_in_years_at_ascent
,age(a.ascent_dt_start, c.date_of_birth) as age_interval_at_ascent
,a.ascent_id
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_start = a.ascent_dt_end
and ast.ascent_successful = true
), youngest as (
select *
from ascents_with_ages
where row_number = 1
)
select
y.grade
,'<a href="/climber/' || y.climber_id::varchar || '">' || y.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || y.climb_id::varchar || '">' || y.climb_name || '</a>' as "Climb"
,y.age_in_days_at_ascent as "Age (Days)"
,y.age_in_years_at_ascent || ' years ' || extract(days FROM y.ascent_dt_start - (y.date_of_birth + make_interval(years => y.age_in_years_at_ascent))) || ' days' AS "Age"
from
youngest y
where
case
when grade_system_id = 1 and order_on >= 13 then 1 -- sport
when grade_system_id = 2 and order_on >= 60 then 1 -- trad
when grade_system_id = 3 and order_on >= 37 then 1 -- boulder
else 0
end = 1
and climb_type_id in (1,2,3)
order by
grade_system_id
,order_on
Diff
--- before
|
|||||||
| 4870 | 24th March 2026 | 01:01:10 UTC | ben_sandi | list | Oldest Ascents (with date ranges) | list_definition | |
|
Before
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by a.ascent_dt_start - c.date_of_birth_end desc, a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,a.ascent_dt_start - c.date_of_birth_end as min_age_in_days_at_ascent
,a.ascent_dt_end - c.date_of_birth_start as max_age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer as min_age_in_years_at_ascent
,extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
where
a.ascent_dt_start is not null
and a.ascent_dt_end is not null
), oldest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
o.grade
,'<a href="/climber/' || o.climber_id::varchar || '">' || o.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || o.climb_id::varchar || '">' || o.climb_name || '</a>' as "Climb"
,o.min_age_in_days_at_ascent as "Minimum age (days)"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days'
else
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days to ' ||
o.max_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_end - (o.date_of_birth_start + make_interval(years => o.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
oldest o
where
case
when o.grade_system_id = 1 and o.order_on >= 13 then 1
when o.grade_system_id = 2 and o.order_on >= 60 then 1
when o.grade_system_id = 3 and o.order_on >= 37 then 1
else 0
end = 1
and o.climb_type_id in (1,2,3)
order by
o.grade_system_id
,o.order_on
After
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by a.ascent_dt_start - c.date_of_birth_end desc, a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,a.ascent_dt_start - c.date_of_birth_end as min_age_in_days_at_ascent
,a.ascent_dt_end - c.date_of_birth_start as max_age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer as min_age_in_years_at_ascent
,extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_start is not null
and a.ascent_dt_end is not null
and ast.ascent_successful = true
), oldest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
o.grade
,'<a href="/climber/' || o.climber_id::varchar || '">' || o.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || o.climb_id::varchar || '">' || o.climb_name || '</a>' as "Climb"
,o.min_age_in_days_at_ascent as "Minimum age (days)"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days'
else
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days to ' ||
o.max_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_end - (o.date_of_birth_start + make_interval(years => o.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
oldest o
where
case
when o.grade_system_id = 1 and o.order_on >= 13 then 1
when o.grade_system_id = 2 and o.order_on >= 60 then 1
when o.grade_system_id = 3 and o.order_on >= 37 then 1
else 0
end = 1
and o.climb_type_id in (1,2,3)
order by
o.grade_system_id
,o.order_on
Diff
--- before
|
|||||||
| 4871 | 24th March 2026 | 00:59:35 UTC | ben_sandi | list | Youngest Ascents (with date ranges) | list_definition | |
|
Before
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by a.ascent_dt_end - c.date_of_birth_start asc, a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,a.ascent_dt_start - c.date_of_birth_end as min_age_in_days_at_ascent
,a.ascent_dt_end - c.date_of_birth_start as max_age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer as min_age_in_years_at_ascent
,extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
where
a.ascent_dt_start is not null
and a.ascent_dt_end is not null
), oldest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
o.grade
,'<a href="/climber/' || o.climber_id::varchar || '">' || o.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || o.climb_id::varchar || '">' || o.climb_name || '</a>' as "Climb"
,o.min_age_in_days_at_ascent as "Minimum age (days)"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days'
else
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days to ' ||
o.max_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_end - (o.date_of_birth_start + make_interval(years => o.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
oldest o
where
case
when o.grade_system_id = 1 and o.order_on >= 13 then 1
when o.grade_system_id = 2 and o.order_on >= 60 then 1
when o.grade_system_id = 3 and o.order_on >= 37 then 1
else 0
end = 1
and o.climb_type_id in (1,2,3)
order by
o.grade_system_id
,o.order_on
After
with climbers_with_dobs as (
select
c.climber_id
,c.climber_name
,c.date_of_birth_start
,c.date_of_birth_end
from
climbers c
where
c.deleted_on is null
and c.date_of_birth_start is not null
and c.date_of_birth_end is not null
), ascents_with_ages as (
select
row_number() over (
partition by g.grade_id
order by a.ascent_dt_end - c.date_of_birth_start asc, a.ascent_dt_start asc
) as row_number
,c.climber_id
,c.climber_name
,cl.climb_id
,cl.climb_name
,g.grade_id
,g.grade_system_id
,g.climb_type_id
,g.order_on
,g.grade
,a.ascent_dt_start
,a.ascent_dt_end
,c.date_of_birth_start
,c.date_of_birth_end
,a.ascent_dt_start - c.date_of_birth_end as min_age_in_days_at_ascent
,a.ascent_dt_end - c.date_of_birth_start as max_age_in_days_at_ascent
,extract(year from age(a.ascent_dt_start, c.date_of_birth_end))::integer as min_age_in_years_at_ascent
,extract(year from age(a.ascent_dt_end, c.date_of_birth_start))::integer as max_age_in_years_at_ascent
from
ascents a
inner join climbers_with_dobs c
on a.climber_id = c.climber_id
and a.deleted_on is null
inner join climbs cl
on cl.climb_id = a.climb_id
and cl.deleted_on is null
inner join grades g
on cl.grade_id = g.grade_id
inner join ascent_styles ast
on a.ascent_style_id = ast.ascent_style_id
where
a.ascent_dt_start is not null
and a.ascent_dt_end is not null
and ast.ascent_successful = true
), oldest as (
select
*
from
ascents_with_ages
where
row_number = 1
)
select
o.grade
,'<a href="/climber/' || o.climber_id::varchar || '">' || o.climber_name || '</a>' as "Climber"
,'<a href="/climb/' || o.climb_id::varchar || '">' || o.climb_name || '</a>' as "Climb"
,o.min_age_in_days_at_ascent as "Minimum age (days)"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days'
else
o.min_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_start - (o.date_of_birth_end + make_interval(years => o.min_age_in_years_at_ascent))) ||
' days to ' ||
o.max_age_in_years_at_ascent || ' years ' ||
extract(days from o.ascent_dt_end - (o.date_of_birth_start + make_interval(years => o.max_age_in_years_at_ascent))) ||
' days'
end as "Age"
,case
when o.min_age_in_days_at_ascent = o.max_age_in_days_at_ascent then ''
else '✓'
end as "Dates Needed"
from
oldest o
where
case
when o.grade_system_id = 1 and o.order_on >= 13 then 1
when o.grade_system_id = 2 and o.order_on >= 60 then 1
when o.grade_system_id = 3 and o.order_on >= 37 then 1
else 0
end = 1
and o.climb_type_id in (1,2,3)
order by
o.grade_system_id
,o.order_on
Diff
--- before
|
|||||||
| 4872 | 24th March 2026 | 00:53:55 UTC | ben_sandi | list | Youngest Ascents (with date ranges) | list_description_pretty | |
|
Before
<p>Main list here: <a href="https://climbing-history.org/list/57/youngest-ascents" rel="noopener noreferrer">https://climbing-history.org/list/57/youngest-ascents</a></p>
<p>The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers <em>maximum possible age of ascent</em> based on the data we have. Ideally we want to source the exact dates for the ascents listed here.</p>
After
<p>Main list here: <a href="https://climbing-history.org/list/57/youngest-ascents" rel="noopener noreferrer">https://climbing-history.org/list/57/youngest-ascents</a></p>
<p>The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers <em>maximum</em> age of ascent. Ideally we want to source the exact dates for the ascents listed here.</p>
|
|||||||
| 4873 | 24th March 2026 | 00:53:55 UTC | ben_sandi | list | Youngest Ascents (with date ranges) | list_description | |
|
Before
Main list here: [https://climbing-history.org/list/57/youngest-ascents](https://climbing-history.org/list/57/youngest-ascents)
The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers *maximum possible age of ascent* based on the data we have. Ideally we want to source the exact dates for the ascents listed here.
After
Main list here: [https://climbing-history.org/list/57/youngest-ascents](https://climbing-history.org/list/57/youngest-ascents)
The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers *maximum* age of ascent. Ideally we want to source the exact dates for the ascents listed here.
Diff
--- before
|
|||||||
| 4874 | 24th March 2026 | 00:53:35 UTC | ben_sandi | list | Oldest Ascents (with date ranges) | list_description_pretty | |
|
Before
<p>Main list here: <a href="https://climbing-history.org/list/82/oldest-ascents" rel="noopener noreferrer">https://climbing-history.org/list/82/oldest-ascents</a></p>
<p>The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers <em>minimum age of ascent</em> based on the data we have. Ideally we want to source the exact dates for the ascents listed here.</p>
After
<p>Main list here: <a href="https://climbing-history.org/list/82/oldest-ascents" rel="noopener noreferrer">https://climbing-history.org/list/82/oldest-ascents</a></p>
<p>The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers <em>minimum</em> age of ascent. Ideally we want to source the exact dates for the ascents listed here.</p>
|
|||||||
| 4875 | 24th March 2026 | 00:53:35 UTC | ben_sandi | list | Oldest Ascents (with date ranges) | list_description | |
|
Before
Main list here: [https://climbing-history.org/list/82/oldest-ascents](https://climbing-history.org/list/82/oldest-ascents)
The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers *minimum age of ascent* based on the data we have. Ideally we want to source the exact dates for the ascents listed here.
After
Main list here: [https://climbing-history.org/list/82/oldest-ascents](https://climbing-history.org/list/82/oldest-ascents)
The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers *minimum* age of ascent. Ideally we want to source the exact dates for the ascents listed here.
Diff
--- before
|
|||||||
| 4876 | 24th March 2026 | 00:53:13 UTC | ben_sandi | list | Oldest Ascents (with date ranges) | list_description_pretty | |
|
Before
<p>Main list here: <a href="https://climbing-history.org/list/82/oldest-ascents" rel="noopener noreferrer">https://climbing-history.org/list/82/oldest-ascents</a></p>
<p>The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers <em>minimum possible age of ascent</em> based on the data we have. Ideally we want to source the exact dates for the ascents listed here.</p>
After
<p>Main list here: <a href="https://climbing-history.org/list/82/oldest-ascents" rel="noopener noreferrer">https://climbing-history.org/list/82/oldest-ascents</a></p>
<p>The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers <em>minimum age of ascent</em> based on the data we have. Ideally we want to source the exact dates for the ascents listed here.</p>
|
|||||||
| 4877 | 24th March 2026 | 00:53:13 UTC | ben_sandi | list | Oldest Ascents (with date ranges) | list_description | |
|
Before
Main list here: [https://climbing-history.org/list/82/oldest-ascents](https://climbing-history.org/list/82/oldest-ascents)
The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers *minimum possible age of ascent* based on the data we have. Ideally we want to source the exact dates for the ascents listed here.
After
Main list here: [https://climbing-history.org/list/82/oldest-ascents](https://climbing-history.org/list/82/oldest-ascents)
The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers *minimum age of ascent* based on the data we have. Ideally we want to source the exact dates for the ascents listed here.
Diff
--- before
|
|||||||
| 4878 | 24th March 2026 | 00:52:56 UTC | ben_sandi | list | Oldest Ascents (with date ranges) | list_description_pretty | |
|
Before
<p>Main list here: <a href="https://climbing-history.org/list/82/oldest-ascents" rel="noopener noreferrer">https://climbing-history.org/list/82/oldest-ascents</a></p>
<p>The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers minimum possible age based on the data we have. Ideally we want to source the exact dates for the ascents listed here.</p>
After
<p>Main list here: <a href="https://climbing-history.org/list/82/oldest-ascents" rel="noopener noreferrer">https://climbing-history.org/list/82/oldest-ascents</a></p>
<p>The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers <em>minimum possible age of ascent</em> based on the data we have. Ideally we want to source the exact dates for the ascents listed here.</p>
|
|||||||
| 4879 | 24th March 2026 | 00:52:56 UTC | ben_sandi | list | Oldest Ascents (with date ranges) | list_description | |
|
Before
Main list here: [https://climbing-history.org/list/82/oldest-ascents](https://climbing-history.org/list/82/oldest-ascents)
The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers minimum possible age based on the data we have. Ideally we want to source the exact dates for the ascents listed here.
After
Main list here: [https://climbing-history.org/list/82/oldest-ascents](https://climbing-history.org/list/82/oldest-ascents)
The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers *minimum possible age of ascent* based on the data we have. Ideally we want to source the exact dates for the ascents listed here.
Diff
--- before
|
|||||||
| 4880 | 24th March 2026 | 00:52:18 UTC | ben_sandi | list | Youngest Ascents (with date ranges) | list_description_pretty | |
|
Before
<p>Main list here: <a href="https://climbing-history.org/list/57/youngest-ascents" rel="noopener noreferrer">https://climbing-history.org/list/57/youngest-ascents</a></p>
<p>The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers <em>maximum</em> possible age based on the data we have. Ideally we want to source the exact dates for the ascents listed here.</p>
After
<p>Main list here: <a href="https://climbing-history.org/list/57/youngest-ascents" rel="noopener noreferrer">https://climbing-history.org/list/57/youngest-ascents</a></p>
<p>The above list will only show an ascent where we can calculate a climbers exact age at time of ascent. This list instead calculates the range of possible ages and sorts based on the climbers <em>maximum possible age of ascent</em> based on the data we have. Ideally we want to source the exact dates for the ascents listed here.</p>
|
|||||||