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

多表关联查询后如何将重复数据整理为目标关联数组?

解决方案

方案1:单SQL查询+GROUP_CONCAT聚合,PHP拆分字段

先调整SQL语句,用GROUP_CONCAT把多对多关联的用户名、诊断信息合并为字符串,避免返回重复的文档主数据行,之后在PHP中拆分字符串为子数组。

SQL示例

SELECT 
    d.*,
    GROUP_CONCAT(DISTINCT u.username SEPARATOR '|') AS owner_names,
    GROUP_CONCAT(DISTINCT d1.diagnosis_name SEPARATOR '|') AS d_diagnoses,
    GROUP_CONCAT(DISTINCT d2.diagnosis_name SEPARATOR '|') AS a_diagnoses
FROM DocumentsTable d
LEFT JOIN DocOwnersTable do ON d.DocID = do.DocID
LEFT JOIN users u ON do.UserID = u.UserID
LEFT JOIN DocDDiagnosesTables ddt ON d.DocID = ddt.DocID
LEFT JOIN Diagnoses d1 ON ddt.DiagnosisID = d1.DiagnosisID
LEFT JOIN DocADiagnosesTable dat ON d.DocID = dat.DocID
LEFT JOIN Diagnoses d2 ON dat.DiagnosisID = d2.DiagnosisID
WHERE d.DocID = :DocID
GROUP BY d.DocID;

这里用LEFT JOIN防止因无关联用户/诊断丢失文档数据,DISTINCT去除重复的用户名或诊断,SEPARATOR选一个不会出现在内容里的分隔符(若内容含|,可替换为###等特殊字符)。

PHP处理代码

// 假设已完成PDO语句准备与$DocID绑定
$stmt->execute(['DocID' => $DocID]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);

// 拆分聚合字段为子数组
$result['owners'] = !empty($result['owner_names']) ? explode('|', $result['owner_names']) : [];
$result['d_diagnoses_list'] = !empty($result['d_diagnoses']) ? explode('|', $result['d_diagnoses']) : [];
$result['a_diagnoses_list'] = !empty($result['a_diagnoses']) ? explode('|', $result['a_diagnoses']) : [];

// 移除原始聚合字段(可选)
unset($result['owner_names'], $result['d_diagnoses'], $result['a_diagnoses']);

最终$result即为包含子数组的关联数组,满足视图格式化需求。

方案2:分多次查询组装数组

若不想使用聚合函数,可分三次查询:先获取文档主数据,再查询关联用户,最后查询关联诊断,手动组装成目标结构。

步骤1:查询文档主数据

SELECT * FROM DocumentsTable WHERE DocID = :DocID;
$stmt = $pdo->prepare("SELECT * FROM DocumentsTable WHERE DocID = :DocID");
$stmt->execute(['DocID' => $DocID]);
$doc = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$doc) {
    // 处理文档不存在的场景
    exit;
}

步骤2:查询关联用户名

SELECT u.username 
FROM DocOwnersTable do
JOIN users u ON do.UserID = u.UserID
WHERE do.DocID = :DocID;
$stmt = $pdo->prepare("SELECT u.username FROM DocOwnersTable do JOIN users u ON do.UserID = u.UserID WHERE do.DocID = :DocID");
$stmt->execute(['DocID' => $DocID]);
$doc['owners'] = $stmt->fetchAll(PDO::FETCH_COLUMN, 0); // 直接获取用户名数组

步骤3:查询关联诊断信息

-- 查询DocDDiagnosesTables关联的诊断
SELECT d.* FROM DocDDiagnosesTables ddt JOIN Diagnoses d ON ddt.DiagnosisID = d.DiagnosisID WHERE ddt.DocID = :DocID;
-- 查询DocADiagnosesTable关联的诊断
SELECT d.* FROM DocADiagnosesTable dat JOIN Diagnoses d ON dat.DiagnosisID = d.DiagnosisID WHERE dat.DocID = :DocID;
// 获取D类型诊断
$stmt = $pdo->prepare("SELECT d.* FROM DocDDiagnosesTables ddt JOIN Diagnoses d ON ddt.DiagnosisID = d.DiagnosisID WHERE ddt.DocID = :DocID");
$stmt->execute(['DocID' => $DocID]);
$doc['d_diagnoses'] = $stmt->fetchAll(PDO::FETCH_ASSOC);

// 获取A类型诊断
$stmt = $pdo->prepare("SELECT d.* FROM DocADiagnosesTable dat JOIN Diagnoses d ON dat.DiagnosisID = d.DiagnosisID WHERE dat.DocID = :DocID");
$stmt->execute(['DocID' => $DocID]);
$doc['a_diagnoses'] = $stmt->fetchAll(PDO::FETCH_ASSOC);

最终$doc就是包含子数组的目标结构,无重复数据。

原方法无效的原因

多表INNER JOIN后,每一个关联的用户或诊断都会生成新行,fetchAll会返回大量重复的文档主数据行,而array_diff这类函数无法处理这种结构——因为重复的是整行数据,仅关联字段不同。上述两种方案要么通过SQL聚合减少返回行数,要么分查询从根源避免重复。

内容的提问来源于stack exchange,提问作者dr.help

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 07:05:23