historical_experience table tracks career history for contacts in the RevenueBase database. Each row represents one LinkedIn profile with a nested array structure: a jobs array containing job objects, each with an experience array of position records. Use it to understand career trajectories, identify recent job changers, find alumni of specific companies, and build more personalized outreach.
Where the data comes from
Historical experience is derived from professional profiles and public career history. Positions are normalized to titles, seniority, and department where possible. Start and end dates are captured with the precision available from the source (sometimes year-only for older roles). Tenure is calculated from those dates.Counts and coverage
Each row represents one LinkedIn profile with nested arrays: ajobs array containing job objects, each with an experience array of position records. Not every contact has historical experience; fill rates are higher for recent roles and for people with detailed public profiles. Use the fill-rate query below to see coverage and average positions per profile.
Table stats
| Metric | Value |
|---|---|
| Total records | One row per LinkedIn profile (with array of jobs) |
| Update frequency | Monthly (aligned with contacts release) |
| Primary key | linkedin_url |
| Main foreign keys | Join to person table on linkedin_url, join to organization table via rbid_org |
Data dictionary
Fill rates for historical data are typically lower than for current-position data. Older positions, smaller companies, and non-US contacts tend to have less complete records. The table structure uses one row per LinkedIn profile with an array of job positions.Top-level fields
| Field | Type | Description |
|---|---|---|
unique_id | VARCHAR | Unique identifier for this record |
linkedin_url | VARCHAR | LinkedIn profile URL (primary key) |
job_count | INTEGER | Maximum number of jobs for this profile |
jobs | ARRAY | Array of job objects containing experience data |
Jobs array structure
Each element in thejobs array is an object containing:
| Field | Type | Description |
|---|---|---|
rbid | VARCHAR | RevenueBase person identifier (from person table) |
rbid_pao | VARCHAR | RevenueBase person-at-organization identifier |
rbid_org | VARCHAR | RevenueBase organization identifier |
linkedin_id | INTEGER | LinkedIn company page ID (from organization table) |
email_address | VARCHAR | Email address (from person table) |
experience | ARRAY | Array of experience objects containing position details |
Experience array structure
Each element in theexperience array within a job object contains:
| Field | Type | Description |
|---|---|---|
job_title | VARCHAR | Job title for this position |
job_org_name | VARCHAR | Company name for this position |
job_org_linkedin_url | VARCHAR | LinkedIn company page URL |
job_function | VARCHAR | Department or functional area |
job_is_current | BOOLEAN | Whether this is the person’s current position |
One row per LinkedIn profile with nested arrays. Each row contains a
jobs array. Each job object contains an experience array with one or more position records. A person may have multiple positions at the same company (different roles over time), which is why experience is an array. Use nested array functions to query and filter individual positions.The
experience array structure may include additional fields like start_date, end_date, and other position-related attributes depending on data availability. Query the nested arrays to access individual job positions.Joining to other tables
Thejobs array contains rbid, rbid_org, and email_address that you can use to join to other tables. The experience array within each job contains position-specific details:
| Approach | When to use |
|---|---|
| Join to person table | Use jobs[].rbid or join on linkedin_url to get current contact information |
| Join to organization table | Use jobs[].rbid_org to get company firmographics and HQ address for that employer |
| Access position details | Flatten both jobs and experience arrays to access individual position fields like job_title, job_org_name, job_function, job_is_current |
| Contact’s current location | For “where does this person live now,” use contacts (CITY_PER, STATE_NAME_PER, COUNTRY_NAME_PER), not historical experience |
Common use cases
Find recent job changers
Find recent job changers
People who just started a new role are often more receptive to new tools. Flatten both the
jobs and experience arrays and filter for positions where experience.job_is_current = TRUE. Join to the person table and filter by UPDATED_AT_PER to find recently updated profiles.Company alumni targeting
Company alumni targeting
Find everyone who used to work at a specific company by flattening both arrays and filtering for
experience.job_org_linkedin_url matching the target company, or use jobs[].rbid_org to join to the organization table. Filter for experience.job_is_current = FALSE. Useful for selling to former champions who already know your space.Career trajectory analysis
Career trajectory analysis
Flatten both arrays and compare
job_title, job_function, and job_org_name across positions for a profile. Use job_count to identify profiles with multiple positions, then analyze the progression in the nested arrays.Multiple positions at same company
Multiple positions at same company
Some profiles may have multiple entries in the
experience array within the same job object, representing different roles at the same company over time. Flatten both arrays to see all positions and their progression.Joining this table
Joinhistorical_experience to PER_LATEST table on linkedin_url to get current contact info. Flatten both the jobs and experience arrays to access individual positions. Join to ORG_LATEST table using jobs[].rbid_org when you need firmographics or HQ address for a specific role.
Flattening the nested arrays
To work with individual positions, you need to flatten both thejobs array and the experience array within each job. Here’s a pattern for Snowflake:
Historical experience + contacts (recent job changers with contact info)
Historical experience + contacts + companies (alumni with HQ location)
How to calculate fill rates
Use this to see how many profiles you have, how many positions total, and how complete key fields are.Sample queries
Recent job changers (last 90 days)
What you’re finding: People who started a new job in the last 90 days, for outreach or lead scoring. Why these fields: We need current contact info from the person table and the new role from the flattened jobs array. Filter for current positions with recent start dates. Logic: Flatten both the jobs and experience arrays, filter to current positions (job_is_current = TRUE). Join to person table for contact info. Use UPDATED_AT_PER to identify recently updated profiles.
Alumni of a specific company
What you’re finding: People who used to work at a given company (e.g. Salesforce), with current contact info, for alumni campaigns or competitive targeting. Why these fields: Filter the jobs array for the target company domain and non-current positions. Join to person table for current contact info. Logic: Flatten both arrays, filter by target company LinkedIn URL pattern and non-current positions. Join to person table for email and current context. Order by profile update date descending.Profiles with multiple positions
What you’re finding: Profiles that have held multiple positions, useful for career trajectory analysis. Why these fields: Usejob_count to identify profiles with multiple positions, then flatten to see all positions.
Logic: Filter for profiles with job_count > 1, then flatten both arrays to see all positions.
