如何在单行中左连接两张表(Oracle 11g/标准SQL)并实现指定结果
实现单行左连接的标准化方案(Oracle 11g/标准SQL)
嘿,这个需求完全可以用标准化的SQL语法来实现,不用什么冷门技巧~ 下面根据你要的单行呈现方式,给你两种常见的方案,不管是Oracle 11g还是标准SQL都能覆盖到:
方案1:将子项拼接为单个字符串(最常用)
如果只是想把父项对应的所有子项放在同一行的一个字段里,Oracle 11g自带的LISTAGG函数就非常合适,这也是Oracle官方推荐的字符串聚合方法;如果是标准SQL环境,可使用STRING_AGG(不同数据库可能有细微差异,但逻辑一致)。
示例代码(Oracle 11g)
-- 假设父表为parent,主键parent_id;子表为child,主键child_id,关联字段parent_id SELECT p.parent_id, -- 用逗号分隔子项,也可以换成其他分隔符 LISTAGG(c.child_id, ', ') WITHIN GROUP (ORDER BY c.child_id) AS child_items FROM parent p -- 左连接保证父表所有行都被保留,哪怕没有子项 LEFT JOIN child c ON p.parent_id = c.parent_id GROUP BY p.parent_id;
效果:p1会显示c1, c2,p2的child_items字段为NULL(可以用NVL(LISTAGG(...), '无子女')替换成你想要的提示文本)。
标准SQL版本(兼容多数数据库)
SELECT p.parent_id, STRING_AGG(c.child_id, ', ') AS child_items FROM parent p LEFT JOIN child c ON p.parent_id = c.parent_id GROUP BY p.parent_id;
方案2:将子项拆分为单独的列(如child1、child2)
如果需要把每个子项放在独立的字段里(比如p1的两个子项分别显示为child_1和child_2),可以用窗口函数ROW_NUMBER()结合条件聚合来实现,这是标准SQL兼容的写法,Oracle 11g也支持。
示例代码
WITH ranked_children AS ( -- 给每个父项的子项按顺序编号 SELECT child_id, parent_id, ROW_NUMBER() OVER (PARTITION BY parent_id ORDER BY child_id) AS rn FROM child ) SELECT p.parent_id, -- 取第1个、第2个子项,没有的话显示NULL MAX(CASE WHEN rc.rn = 1 THEN rc.child_id END) AS child_1, MAX(CASE WHEN rc.rn = 2 THEN rc.child_id END) AS child_2 FROM parent p LEFT JOIN ranked_children rc ON p.parent_id = rc.parent_id GROUP BY p.parent_id;
效果:p1的child_1为c1,child_2为c2;p2的两个子字段都是NULL。如果子项数量不确定,也可以用Oracle 11g的PIVOT语法,写法会更简洁,但兼容性稍差。
核心逻辑其实就是:用LEFT JOIN保留父表的所有行,再通过聚合函数(LISTAGG/STRING_AGG/MAX)或窗口函数将子表的多行数据合并到父表的单行中,这些都是SQL标准里的常规操作,不需要特殊的连接类型或保留关键字,组合基础语法就能实现。
内容的提问来源于stack exchange,提问作者Prefijo Sustantivo
相关产品推荐
相关产品推荐

