# Methodology: Veterinary chain locations: what 7,961 listed sites show

Every figure on the page is an aggregate. No location-level row, address or phone number is published. Each block below gives the source, the exact query, the row counts and the minimum group size applied.

### Methodology: Listed locations per corporate veterinary chain (US)

- **Asset:** US corporate veterinary chain locations (chain location-listing crawl) (csv, public_source); owner Rome (Vettica).
- **Collection method:** Crawled the location listings of 27 corporate veterinary groups on 27-28 September 2026: public location finders (23 chains) and careers/office listings (4 chains: Mission Veterinary Partners, Vetcor, Western Veterinary Partners, Heartland Veterinary Partners: 1,867 of 7,961 rows), using rendered pages, locator APIs and careers-site feeds; one row per listed location.
- **As of:** 2026-09-30; cadence quarterly_index; contribution type first_party.
- **Rows:** 7965 input; 7961 after filters and de-duplication.
- **Threshold:** at least 5 source rows per published group; 27 of 27 groups published (0 below threshold, 0 secondary).
- **Engine:** pandas.read_csv(dtype=str, keep_default_na=False) -> in-memory SQLite table "asset"

```sql
WITH filtered AS (
  SELECT MIN("brand") AS "brand", MIN("chain") AS "chain", MIN("state") AS "state", MIN("street") AS "street", MIN("zip") AS "zip"
  FROM (SELECT *, ROW_NUMBER() OVER () AS "_rid" FROM "asset") src
  GROUP BY LOWER(TRIM("brand")), LOWER(TRIM("street")), LOWER(TRIM("zip")), CASE WHEN COALESCE(TRIM("brand"), '') = '' OR COALESCE(TRIM("street"), '') = '' OR COALESCE(TRIM("zip"), '') = '' THEN "_rid" END
),
rows AS (
  SELECT *,
    CASE "chain" WHEN ? THEN ? WHEN ? THEN ? ELSE ? END AS "format"
  FROM filtered
)
SELECT "brand", "format", COUNT(*) AS "locations", COUNT(DISTINCT NULLIF(TRIM("state"), '')) AS "states", COUNT(*) AS "_n_rows"
FROM rows
GROUP BY "brand", "format"
HAVING COUNT(*) >= ?
```
Parameters: `["tractor_supply_petvet", "host-store clinic sites", "vip_petcare", "host-store clinic sites", "clinic and hospital locations", 5]`

### Methodology: Chain locations by format, compared with the Census count of veterinary establishments

- **Asset:** US corporate veterinary chain locations (chain location-listing crawl) (csv, public_source); owner Rome (Vettica).
- **Collection method:** Crawled the location listings of 27 corporate veterinary groups on 27-28 September 2026: public location finders (23 chains) and careers/office listings (4 chains: Mission Veterinary Partners, Vetcor, Western Veterinary Partners, Heartland Veterinary Partners: 1,867 of 7,961 rows), using rendered pages, locator APIs and careers-site feeds; one row per listed location.
- **As of:** 2026-09-30; cadence quarterly_index; contribution type derived.
- **Rows:** 7965 input; 7961 after filters and de-duplication.
- **Threshold:** at least 5 source rows per published group; 2 of 2 groups published (0 below threshold, 0 secondary).
- **Engine:** pandas.read_csv(dtype=str, keep_default_na=False) -> in-memory SQLite table "asset"

```sql
WITH filtered AS (
  SELECT MIN("brand") AS "brand", MIN("chain") AS "chain", MIN("street") AS "street", MIN("zip") AS "zip"
  FROM (SELECT *, ROW_NUMBER() OVER () AS "_rid" FROM "asset") src
  GROUP BY LOWER(TRIM("brand")), LOWER(TRIM("street")), LOWER(TRIM("zip")), CASE WHEN COALESCE(TRIM("brand"), '') = '' OR COALESCE(TRIM("street"), '') = '' OR COALESCE(TRIM("zip"), '') = '' THEN "_rid" END
),
rows AS (
  SELECT *,
    CASE "chain" WHEN ? THEN ? WHEN ? THEN ? ELSE ? END AS "format"
  FROM filtered
)
SELECT "format", COUNT(*) AS "locations", COUNT(DISTINCT NULLIF(TRIM("brand"), '')) AS "chains", COUNT(*) AS "_n_rows"
FROM rows
GROUP BY "format"
HAVING COUNT(*) >= ?
```
Parameters: `["tractor_supply_petvet", "host-store clinic sites", "vip_petcare", "host-store clinic sites", "clinic and hospital locations", 5]`

### Methodology: Clinic and hospital locations of corporate chains per state

- **Asset:** US corporate veterinary chain locations (chain location-listing crawl) (csv, public_source); owner Rome (Vettica).
- **Collection method:** Crawled the location listings of 27 corporate veterinary groups on 27-28 September 2026: public location finders (23 chains) and careers/office listings (4 chains: Mission Veterinary Partners, Vetcor, Western Veterinary Partners, Heartland Veterinary Partners: 1,867 of 7,961 rows), using rendered pages, locator APIs and careers-site feeds; one row per listed location.
- **As of:** 2026-09-30; cadence quarterly_index; contribution type first_party.
- **Rows:** 7965 input; 5136 after filters and de-duplication.
- **Threshold:** at least 5 source rows per published group; 51 of 51 groups published (0 below threshold, 0 secondary).
- **Engine:** pandas.read_csv(dtype=str, keep_default_na=False) -> in-memory SQLite table "asset"

```sql
WITH filtered AS (
  SELECT MIN("brand") AS "brand", MIN("state") AS "state", MIN("street") AS "street", MIN("zip") AS "zip"
  FROM (SELECT *, ROW_NUMBER() OVER () AS "_rid" FROM "asset"
  WHERE "chain" NOT IN (?, ?)) src
  GROUP BY LOWER(TRIM("brand")), LOWER(TRIM("street")), LOWER(TRIM("zip")), CASE WHEN COALESCE(TRIM("brand"), '') = '' OR COALESCE(TRIM("street"), '') = '' OR COALESCE(TRIM("zip"), '') = '' THEN "_rid" END
),
rows AS (
  SELECT *
  FROM filtered
)
SELECT "state", COUNT(*) AS "locations", COUNT(DISTINCT NULLIF(TRIM("brand"), '')) AS "chains", COUNT(*) AS "_n_rows"
FROM rows
GROUP BY "state"
HAVING COUNT(*) >= ?
```
Parameters: `["tractor_supply_petvet", "vip_petcare", 5]`

### Methodology: Cities with the most corporate chain clinic and hospital locations

- **Asset:** US corporate veterinary chain locations (chain location-listing crawl) (csv, public_source); owner Rome (Vettica).
- **Collection method:** Crawled the location listings of 27 corporate veterinary groups on 27-28 September 2026: public location finders (23 chains) and careers/office listings (4 chains: Mission Veterinary Partners, Vetcor, Western Veterinary Partners, Heartland Veterinary Partners: 1,867 of 7,961 rows), using rendered pages, locator APIs and careers-site feeds; one row per listed location.
- **As of:** 2026-09-30; cadence quarterly_index; contribution type first_party.
- **Rows:** 7965 input; 5103 after filters and de-duplication.
- **Threshold:** at least 5 source rows per published group; 159 of 2691 groups published (2532 below threshold, 0 secondary).
- **Engine:** pandas.read_csv(dtype=str, keep_default_na=False) -> in-memory SQLite table "asset"

```sql
WITH filtered AS (
  SELECT MIN("brand") AS "brand", MIN("city") AS "city", MIN("state") AS "state", MIN("street") AS "street", MIN("zip") AS "zip"
  FROM (SELECT *, ROW_NUMBER() OVER () AS "_rid" FROM "asset"
  WHERE "chain" NOT IN (?, ?)
    AND COALESCE(TRIM("city"), '') <> '') src
  GROUP BY LOWER(TRIM("brand")), LOWER(TRIM("street")), LOWER(TRIM("zip")), CASE WHEN COALESCE(TRIM("brand"), '') = '' OR COALESCE(TRIM("street"), '') = '' OR COALESCE(TRIM("zip"), '') = '' THEN "_rid" END
),
rows AS (
  SELECT *
  FROM filtered
)
SELECT "city", "state", COUNT(*) AS "locations", COUNT(DISTINCT NULLIF(TRIM("brand"), '')) AS "chains", COUNT(*) AS "_n_rows"
FROM rows
GROUP BY "city", "state"
HAVING COUNT(*) >= ?
```
Parameters: `["tractor_supply_petvet", "vip_petcare", 5]`

### Methodology: Chain clinic and hospital locations per 100 licensed facility records (FL, MO, KS)

- **Asset:** US corporate veterinary chain locations (chain location-listing crawl) (csv, public_source); owner Rome (Vettica).
- **Collection method:** Crawled the location listings of 27 corporate veterinary groups on 27-28 September 2026: public location finders (23 chains) and careers/office listings (4 chains: Mission Veterinary Partners, Vetcor, Western Veterinary Partners, Heartland Veterinary Partners: 1,867 of 7,961 rows), using rendered pages, locator APIs and careers-site feeds; one row per listed location.
- **As of:** 2026-09-30; cadence quarterly_index; contribution type derived.
- **Rows:** 7965 input; 560 after filters and de-duplication.
- **Threshold:** at least 5 source rows per published group; 3 of 3 groups published (0 below threshold, 0 secondary).
- **Engine:** pandas.read_csv(dtype=str, keep_default_na=False) -> in-memory SQLite table "asset"

```sql
WITH filtered AS (
  SELECT MIN("brand") AS "brand", MIN("state") AS "state", MIN("street") AS "street", MIN("zip") AS "zip"
  FROM (SELECT *, ROW_NUMBER() OVER () AS "_rid" FROM "asset"
  WHERE "chain" NOT IN (?, ?)
    AND "state" IN (?, ?, ?)) src
  GROUP BY LOWER(TRIM("brand")), LOWER(TRIM("street")), LOWER(TRIM("zip")), CASE WHEN COALESCE(TRIM("brand"), '') = '' OR COALESCE(TRIM("street"), '') = '' OR COALESCE(TRIM("zip"), '') = '' THEN "_rid" END
),
rows AS (
  SELECT *
  FROM filtered
)
SELECT "state", COUNT(*) AS "locations", COUNT(DISTINCT NULLIF(TRIM("brand"), '')) AS "chains", COUNT(*) AS "_n_rows"
FROM rows
GROUP BY "state"
HAVING COUNT(*) >= ?
```
Parameters: `["tractor_supply_petvet", "vip_petcare", "FL", "MO", "KS", 5]`

Denominator `registry_facilities` from `vettica-registry-facilities` (facility records in the state board's registry extract (24-25 September 2026)): published counts {"FL": 3127, "MO": 1001, "KS": 678}; threshold 5.

```sql
WITH filtered AS (
  SELECT "source_key"
  FROM "asset"
  WHERE "source_key" IN (?, ?, ?)
),
rows AS (
  SELECT *,
    CASE "source_key" WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? ELSE ? END AS "registry_state"
  FROM filtered
)
SELECT "registry_state", COUNT(*) AS "count", COUNT(*) AS "_n_rows"
FROM rows
GROUP BY "registry_state"
HAVING COUNT(*) >= ?
```

### Methodology: Which states license veterinary facilities and publish a bulk roster

- **Asset:** Veterinary facility-license registry inventory, 50 states + DC (csv, public_source); owner Rome (Vettica).
- **Collection method:** Checked each state veterinary board's website on 28 September 2026 for a facility license and a public bulk roster; evidence URL per state.
- **As of:** 2026-09-30; cadence quarterly_index; contribution type first_party.
- **Rows:** 51 input; 51 after filters and de-duplication.
- **Threshold:** at least 1 source rows per published group; 6 of 6 groups published (0 below threshold, 0 secondary).
- **Engine:** pandas.read_csv(dtype=str, keep_default_na=False) -> in-memory SQLite table "asset"

```sql
WITH filtered AS (
  SELECT "bulk_feasible", "licenses_facilities"
  FROM "asset"
),
rows AS (
  SELECT *,
    CASE "licenses_facilities" WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? ELSE ? END AS "licensing",
    CASE "bulk_feasible" WHEN ? THEN ? WHEN ? THEN ? WHEN ? THEN ? ELSE ? END AS "availability"
  FROM filtered
)
SELECT "licensing", "availability", COUNT(*) AS "states", COUNT(*) AS "_n_rows"
FROM rows
GROUP BY "licensing", "availability"
HAVING COUNT(*) >= ?
```
Parameters: `["yes", "license veterinary facilities", "no", "do not license veterinary facilities", "limited", "license only some facility types", "licensing not recorded", "yes", "a no-cost bulk roster", "held", "a search-only roster (no public bulk file)", "no", "no no-cost bulk roster", "roster availability not recorded", 1]`

### Methodology: Listed locations per chain per state (cells with at least 5 locations)

- **Asset:** US corporate veterinary chain locations (chain location-listing crawl) (csv, public_source); owner Rome (Vettica).
- **Collection method:** Crawled the location listings of 27 corporate veterinary groups on 27-28 September 2026: public location finders (23 chains) and careers/office listings (4 chains: Mission Veterinary Partners, Vetcor, Western Veterinary Partners, Heartland Veterinary Partners: 1,867 of 7,961 rows), using rendered pages, locator APIs and careers-site feeds; one row per listed location.
- **As of:** 2026-09-30; cadence quarterly_index; contribution type dataset.
- **Rows:** 7965 input; 7961 after filters and de-duplication.
- **Threshold:** at least 5 source rows per published group; 365 of 712 groups published (347 below threshold, 0 secondary).
- **Engine:** pandas.read_csv(dtype=str, keep_default_na=False) -> in-memory SQLite table "asset"

```sql
WITH filtered AS (
  SELECT MIN("brand") AS "brand", MIN("state") AS "state", MIN("street") AS "street", MIN("zip") AS "zip"
  FROM (SELECT *, ROW_NUMBER() OVER () AS "_rid" FROM "asset") src
  GROUP BY LOWER(TRIM("brand")), LOWER(TRIM("street")), LOWER(TRIM("zip")), CASE WHEN COALESCE(TRIM("brand"), '') = '' OR COALESCE(TRIM("street"), '') = '' OR COALESCE(TRIM("zip"), '') = '' THEN "_rid" END
),
rows AS (
  SELECT *
  FROM filtered
)
SELECT "brand", "state", COUNT(*) AS "locations", COUNT(*) AS "_n_rows"
FROM rows
GROUP BY "brand", "state"
HAVING COUNT(*) >= ?
```
Parameters: `[5]`

### Methodology: Facility-license registry availability per state (map data)

- **Asset:** Veterinary facility-license registry inventory, 50 states + DC (csv, public_source); owner Rome (Vettica).
- **Collection method:** Checked each state veterinary board's website on 28 September 2026 for a facility license and a public bulk roster; evidence URL per state.
- **As of:** 2026-09-30; cadence quarterly_index; contribution type dataset.
- **Rows:** 51 input; 51 after filters and de-duplication.
- **Threshold:** at least 1 source rows per published group; 51 of 51 groups published (0 below threshold, 0 secondary).
- **Engine:** pandas.read_csv(dtype=str, keep_default_na=False) -> in-memory SQLite table "asset"

```sql
WITH filtered AS (
  SELECT "bulk_feasible", "licenses_facilities", "state_code"
  FROM "asset"
),
rows AS (
  SELECT *
  FROM filtered
)
SELECT "state_code", "licenses_facilities", "bulk_feasible", COUNT(*) AS "states", COUNT(*) AS "_n_rows"
FROM rows
GROUP BY "state_code", "licenses_facilities", "bulk_feasible"
HAVING COUNT(*) >= ?
```
Parameters: `[1]`

