U.S. supply chain tables

Question

What share of Vietnam’s top US shippers already shipped from China in 2016–17?

Shipper continuity summary - what share of top-50 Vietnam shippers (2022-2025) were also China shippers in 2016-17

Answer

Of the 200 largest Vietnam shipper strings on US ocean bills from 2022–25 (weight above 1,000 kg), 94 also appear on China bills in 2016–17 — 47% of names and 48.8% of the 509,801 bills in that top 200. That is overlap of filing strings, not a corporate-family or plant-move identifier. Half the top Vietnam names are new to the 2016–17 China file under this test.

Cite this page if you need the table. Related: China Plus One working paper · all tables

Result

1 row · US ocean AMS bills of lading (Kirchner bols), arrivals 2014–2025.

Also China shippers, 2016–17 Not on China bills, 2016–17 Top Vietnam shippers Name overlap % Unique bills in top 200 Bills from overlapping names Bill overlap %
94 106 200 47 509,801 248,585 48.80

Query

WITH china_shippers_2016_17 AS (
    SELECT upperUTF8(trimBoth(shipper_name_std)) AS sname
    FROM bols
    WHERE actual_arrival_date >= toDate('2016-01-01')
      AND actual_arrival_date <= toDate('2017-12-31')
      AND (match(upperUTF8(country), 'CHINA|ZHONGHUA') OR match(upperUTF8(loading_port), 'SHANGHAI|NINGBO|YANTIAN|SHEKOU|NANSHA|QINGDAO|TIANJIN|DALIAN|GUANGZHOU|XIAMEN'))
      AND length(trimBoth(shipper_name_std)) > 3
    GROUP BY sname
    HAVING count() >= 5
),
vn_top AS (
    SELECT upperUTF8(trimBoth(shipper_name_std)) AS sname,
           uniqExact(bill_of_lading) AS vn_bols
    FROM bols
    WHERE actual_arrival_date >= toDate('2022-01-01')
      AND actual_arrival_date <= toDate('2025-12-31')
      AND (match(upperUTF8(country), 'VIET|VIETNAM') OR match(upperUTF8(loading_port), 'HO CHI MINH|HAI PHONG|HAIPHONG|DA NANG'))
      AND length(trimBoth(shipper_name_std)) > 3
      AND weight_in_kg > 1000
    GROUP BY sname
    ORDER BY vn_bols DESC
    LIMIT 200
)
SELECT
    countIf(cs.sname != '') AS overlap_shippers,
    countIf(cs.sname = '' OR cs.sname IS NULL) AS new_shippers,
    count() AS total_top_200,
    round(100.0 * countIf(cs.sname != '') / count(), 1) AS pct_overlap,
    sum(vn_top.vn_bols) AS total_bols,
    sumIf(vn_top.vn_bols, cs.sname != '') AS overlap_bols,
    round(100.0 * sumIf(vn_top.vn_bols, cs.sname != '') / sum(vn_top.vn_bols), 1) AS pct_bols_overlap
FROM vn_top
LEFT JOIN china_shippers_2016_17 AS cs ON vn_top.sname = cs.sname