You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用MySQL从序列化字符串中提取所有order_id值并拼接?

从MySQL中的PHP序列化字符串提取所有order_id并拼接成列表

给定一段PHP序列化字符串(示例如下),需要用MySQL查询提取其中所有order_id对应的数值,拼成逗号分隔的列表。之前用SUBSTRING_INDEX写的查询只能拿到第一个匹配的order_id,没法提取全部,下面是可行的解决方法:

示例序列化字符串:

a:4:{s:11:"customersId";i:381032;s:12:"commerceName";s:9:"amazonmws";s:9:"serviceId";i:32042;s:9:"trackings";a:2:{i:0;a:10:{s:12:"customers_id";i:381032;s:13:"commerce_name";s:9:"amazonmws";s:10:"service_id";i:32042;s:15:"commerce_ref_id";s:19:"112-1414980-3467405";s:12:"order_number";i:151434392;s:11:"tracking_no";s:15:"995365613134160";s:7:"carrier";s:3:"FDX";s:8:"order_id";i:151434392;s:7:"details";a:1:{i:0;a:2:{s:4:"wsku";s:12:"KZW4OC-F0015";s:3:"qty";s:9:"000000001";}}s:20:"commerce_account_key";N;}i:1;a:10:{s:12:"customers_id";i:381032;s:13:"commerce_name";s:9:"amazonmws";s:10:"service_id";i:32042;s:15:"commerce_ref_id";s:19:"002-5809777-9709040";s:12:"order_number";i:151536332;s:11:"tracking_no";s:15:"995365613134153";s:7:"carrier";s:3:"FDX";s:8:"order_id";i:151536332;s:7:"details";a:1:{i:0;a:2:{s:4:"wsku";s:12:"KZW4OC-F0011";s:3:"qty";s:9:"000000001";}}s:20:"commerce_account_key";N;}}}

你之前尝试的查询(仅返回单个order_id):

SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('serialized_string','"order_id";i:',-1),';s:7:',1);

解决方案

方法1:递归CTE(MySQL 8.0+可用)

递归CTE可以循环遍历字符串,提取所有匹配的order_id,最后用GROUP_CONCAT拼成列表。假设你的表是your_table,存序列化字符串的字段是serialized_data,执行以下查询:

WITH RECURSIVE cte AS (
    -- 先提取第一个order_id,同时保留剩下的字符串
    SELECT
        SUBSTRING_INDEX(SUBSTRING_INDEX(serialized_data, '"order_id";i:', -1), ';', 1) AS order_id,
        SUBSTRING(serialized_data, LOCATE('"order_id";i:', serialized_data) + LENGTH('"order_id";i:') + LENGTH(SUBSTRING_INDEX(SUBSTRING_INDEX(serialized_data, '"order_id";i:', -1), ';', 1))) AS remaining_data
    FROM your_table
    WHERE serialized_data LIKE '%"order_id";i:%'
    
    UNION ALL
    
    -- 递归提取剩余字符串里的order_id,直到没有匹配项
    SELECT
        SUBSTRING_INDEX(SUBSTRING_INDEX(remaining_data, '"order_id";i:', -1), ';', 1) AS order_id,
        SUBSTRING(remaining_data, LOCATE('"order_id";i:', remaining_data) + LENGTH('"order_id";i:') + LENGTH(SUBSTRING_INDEX(SUBSTRING_INDEX(remaining_data, '"order_id";i:', -1), ';', 1))) AS remaining_data
    FROM cte
    WHERE remaining_data LIKE '%"order_id";i:%'
)
SELECT GROUP_CONCAT(DISTINCT order_id ORDER BY order_id) AS order_id_list
FROM cte;

方法2:数字表匹配(兼容MySQL 5.x)

如果你的MySQL版本不支持CTE,可以先建一个临时数字表,用来对应order_id出现的次数:

  1. 创建临时数字表(这里生成10行,不够的话可以多插几行):
CREATE TEMPORARY TABLE numbers (n INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT);
INSERT INTO numbers VALUES (),(),(),(),(),(),(),(),(),();
  1. 执行查询提取所有order_id并拼接:
SELECT GROUP_CONCAT(DISTINCT 
    SUBSTRING_INDEX(SUBSTRING_INDEX(t.serialized_data, '"order_id";i:', n.n), ';', 1) 
    ORDER BY SUBSTRING_INDEX(SUBSTRING_INDEX(t.serialized_data, '"order_id";i:', n.n), ';', 1)
) AS order_id_list
FROM your_table t
JOIN numbers n 
    ON n.n <= (LENGTH(t.serialized_data) - LENGTH(REPLACE(t.serialized_data, '"order_id";i:', ''))) / LENGTH('"order_id";i:')
WHERE t.serialized_data LIKE '%"order_id";i:%';

补充说明

  • DISTINCT是用来去重的,如果你的数据里没有重复的order_id,可以去掉。
  • GROUP_CONCAT默认用逗号分隔,要是需要其他分隔符,比如竖线,就写成GROUP_CONCAT(..., SEPARATOR '|')。

内容的提问来源于stack exchange,提问作者Sandeep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 20:46:35