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