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

如何在MySQL查询中对指定父路径下的子路径仅保留单条记录?

解决方案:在MySQL中筛选每个直接子路径仅保留一条记录

嘿,这个需求完全可以在MySQL里直接实现!核心思路是提取目标路径下的第一个子项(不管是目录还是文件),然后按这个子项分组,每组只保留一条记录。下面给你两种适用不同MySQL版本的方案,都是参数化写法,和你现有的PDO代码兼容,不会有SQL注入风险。

方案一:适用于MySQL 8.0+(窗口函数,更灵活)

窗口函数ROW_NUMBER()可以帮你给每个子项组的记录编号,然后只取编号为1的那条,还能自定义排序规则(比如按路径字典序、创建时间等)。

$dir = 'Volumes/animals/big';
$sql = "WITH ranked_paths AS (
    SELECT 
        path,
        ROW_NUMBER() OVER (
            PARTITION BY REGEXP_SUBSTR(path, CONCAT(TRIM(TRAILING '/' FROM ?), '/([^/]+)'), 1, 1, 'c', 1)
            ORDER BY path -- 可以换成你需要的排序字段,比如`created_at DESC`取最新记录
        ) AS rn
    FROM files
    WHERE id = ? 
      AND path LIKE CONCAT(TRIM(TRAILING '/' FROM ?), '%')
)
SELECT path
FROM ranked_paths
WHERE rn = 1";

$q = $pdo->prepare($sql);
$q->execute([$dir, $id, $dir]);
$array = $q->fetchAll(PDO::FETCH_ASSOC);

代码解释:

  • TRIM(TRAILING '/' FROM ?):统一处理$dir末尾是否带/的情况,避免路径匹配出错。
  • REGEXP_SUBSTR(...):用正则提取$dir/之后的第一个子项(比如horses、elephant、map.jpg),作为分组依据。
  • PARTITION BY ...:按提取的子项分组,给每组的记录编号。
  • ORDER BY path:控制每组取哪条记录,这里取字典序最小的,你可以根据需求修改。

方案二:适用于MySQL 5.x版本(字符串函数+GROUP BY)

如果你的MySQL版本低于8.0,用字符串函数提取子项后分组,配合聚合函数取每组的一条记录即可。

$dir = 'Volumes/animals/big';
$sql = "SELECT MIN(path) AS path
FROM files
WHERE id = ? 
  AND path LIKE CONCAT(TRIM(TRAILING '/' FROM ?), '%')
GROUP BY SUBSTRING_INDEX(
    SUBSTRING(path, LENGTH(TRIM(TRAILING '/' FROM ?)) + 1),
    '/',
    1
)";

$q = $pdo->prepare($sql);
$q->execute([$id, $dir, $dir]);
$array = $q->fetchAll(PDO::FETCH_ASSOC);

代码解释:

  • SUBSTRING(path, LENGTH(...) +1):提取$dir之后的路径部分(比如/horses/shetland/amy.jpg)。
  • SUBSTRING_INDEX(..., '/', 1):从提取的路径中取出第一个/之前的内容,得到第一个子项。
  • GROUP BY ...:按子项分组,MIN(path)取每组字典序最小的记录(换成MAX(path)可以取最大的)。

两种方案都能得到你期望的结果:每个Volumes/animals/big/下的直接子项(目录或文件)仅保留一条记录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:26:58