ben_sandi

Badges

100 Contributions1,000 Contributions10 Posts

Contributions

Posts

1 Day

62

7 Days

76

4 Weeks

113

All Time

6752

Current Streak

1

Longest Streak

13

Contributions Map

Contributions by Country

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

Recent Contributions

Date Time User Type Name Attribute
4841 24th March 2026 10:31:20 UTC ben_sandi climber Yunxi Chen country_name
Before
None
After
China
4842 24th March 2026 10:31:20 UTC ben_sandi climber Yunxi Chen country_id
Before
None
After
74
4843 24th March 2026 10:31:20 UTC ben_sandi climber Yunxi Chen nationality
Before
None
After
CN
4844 24th March 2026 10:31:20 UTC ben_sandi climber Yunxi Chen gender
Before
None
After
true
4845 24th March 2026 10:31:20 UTC ben_sandi climber Yunxi Chen climber_name
Before
None
After
Yunxi Chen
4846 24th March 2026 10:24:07 UTC ben_sandi ascent Théo Blass's ascent of Souvenir du Pic ascent_dt_end
Before
None
After
2020-06-10
4847 24th March 2026 10:24:07 UTC ben_sandi ascent Théo Blass's ascent of Souvenir du Pic ascent_dt_start
Before
None
After
2020-06-10
4848 24th March 2026 10:24:07 UTC ben_sandi ascent Théo Blass's ascent of Souvenir du Pic ascent_type_id
Before
None
After
1
4849 24th March 2026 10:24:07 UTC ben_sandi ascent Théo Blass's ascent of Souvenir du Pic notes_pretty
Before
None
After
<h3>References</h3> <p>[1] <a href="https://www.lacrux.com/en/klettern/record-theo-pale-climbs-8c-route-souvenirs-du-pic-at-the-age-of-10-years/" rel="noopener noreferrer">https://www.lacrux.com/en/klettern/record-theo-pale-climbs-8c-route-souvenirs-du-pic-at-the-age-of-10-years/</a></p>
4850 24th March 2026 10:24:07 UTC ben_sandi ascent Théo Blass's ascent of Souvenir du Pic notes
Before
None
After
### References [1] [https://www.lacrux.com/en/klettern/record-theo-pale-climbs-8c-route-souvenirs-du-pic-at-the-age-of-10-years/](https://www.lacrux.com/en/klettern/record-theo-pale-climbs-8c-route-souvenirs-du-pic-at-the-age-of-10-years/)
Diff
--- before

+++ after

@@ -1 +1,3 @@

-
+### References
+
+[1] [https://www.lacrux.com/en/klettern/record-theo-pale-climbs-8c-route-souvenirs-du-pic-at-the-age-of-10-years/](https://www.lacrux.com/en/klettern/record-theo-pale-climbs-8c-route-souvenirs-du-pic-at-the-age-of-10-years/)
4851 24th March 2026 10:24:07 UTC ben_sandi ascent Théo Blass's ascent of Souvenir du Pic ascent_style_id
Before
None
After
1
4852 24th March 2026 10:24:07 UTC ben_sandi ascent Théo Blass's ascent of Souvenir du Pic climb_id
Before
None
After
5581
4853 24th March 2026 10:24:07 UTC ben_sandi ascent Théo Blass's ascent of Souvenir du Pic climber_id
Before
None
After
2008
4854 24th March 2026 10:04:18 UTC ben_sandi climber Théo Blass age
Before
None
After
16
4855 24th March 2026 10:04:18 UTC ben_sandi climber Théo Blass date_of_birth_pretty
Before
After
Between 1st Nov 2009 and 15th Dec 2009
4856 24th March 2026 10:04:18 UTC ben_sandi climber Théo Blass date_of_birth_end
Before
None
After
2009-12-15
4857 24th March 2026 10:04:18 UTC ben_sandi climber Théo Blass date_of_birth_start
Before
None
After
2009-11-01
4858 24th March 2026 01:50:31 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 ,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
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

+++ after

@@ -73,7 +73,7 @@

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)"
+ ,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 ' ||
4859 24th March 2026 01:50:13 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 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
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 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

+++ after

@@ -76,7 +76,7 @@

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)"
+ ,y.max_age_in_days_at_ascent as "Maximum Age (days)"
,case
when y.ascent_dt_start is null then
'n/a to ' ||
4860 24th March 2026 01:46:43 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> age of ascent. 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 <strong>maximum</strong> age of ascent. Ideally we want to source the exact dates for the ascents listed here.</p>

< Page 243 >