ABAP 基础知识不一样的 leftjoin

作者:ABAP技巧与实战 约 5 分钟阅读 更新日期:2025-03-02 1 年前更新 标签:ABAP, Data Engineering, MM, 开发, 数据工程, 物料管理

原创 无峰 [ ABAP 技巧与实战 ](javascript:void\(0\);)

前言

LEFT JOIN 表示显示左表的全部及关联右表的部分,实际处理时,如果关联的关键字在左表只有一条,但是在右表有N条,

• 结果集显示1条(当右表没有或只有1条时, N=1或0)

• 结果集显示N条(当右表有多条,N>1)

在解决不同字段内容关联的问题时,无意中看到LEFT JOIN 的附加语法MANY TO ONE

.本来以为该语法可以达成仅关联一条的效果.实际测试却发现并发如此.

本文主要介绍LEFT JOIN 中MANY TO ONE 的特点及用法

左连接示意图

该示意图未表达连接部分增加记录数的特性.

ABAP 基础知识不一样的 leftjoin - 封面图
ABAP 基础知识不一样的 leftjoin - 封面图

MANY TO ONE 语法介绍

下图是ABAP语法帮助中关于MANY TO ONE 的描述

ABAP 基础知识不一样的 leftjoin - 封面图
ABAP 基础知识不一样的 leftjoin - 封面图

演示数据

测试: 物料 TEST20210203/1 在MARA 中有一行 , 在MARC中有两行.

ABAP 基础知识不一样的 leftjoin - 封面图
ABAP 基础知识不一样的 leftjoin - 封面图
ABAP 基础知识不一样的 leftjoin - 封面图
ABAP 基础知识不一样的 leftjoin - 封面图

测试场景

以下测试使用 HANA SQL 语句. ABAP SQL语句与之类似.

HANA中使用left out join ABAP中使用 left join .

嵌套SQL的实现方式有很大的差异.

_**01** _

**场景一**

包含两个表的字段.

select a.matnr,b.matnr from mara as a left outer many to one join marc as b on

b.mandt = a.mandt and b.matnr = a.matnr

where a.matnr = 'TEST20210203/1'

结果: 显示两行

_**02** _

**场景二**

仅包含MARA字段

select a.matnr from mara as a left outer many to one join marc as b on b.mandt

= a.mandt and b.matnr = a.matnr

where a.matnr = 'TEST20210203/1'

结果:仅显示一行

_**03** _

**场景三**

计数(*)

select count( * ) from mara as a left outer many to one join marc as b on

b.mandt = a.mandt and b.matnr = a.matnr

where a.matnr = 'TEST20210203/1'

结果:返回值 1.

_**04** _

**场景四**

group 左表字段 count

select a.matnr,count( * ) from mara as a left outer many to one join marc as b

on b.mandt = a.mandt and b.matnr = a.matnr

where a.matnr = 'TEST20210203/1'

group by a.matnr

结果:统计值 1

_**05** _

**场景五**

group 右表字段 count

select b.matnr,count( * ) from mara as a left outer many to one join marc as b

on b.mandt = a.mandt and b.matnr = a.matnr

where a.matnr = 'TEST20210203/1'

group by b.matnr

结果:统计值 2

结论

SQL 会根据SELECT LIST 的字段确定是否优化结果的获取. 如果字段没有涉及到 右表, 则视同为没有关联右表,如果涉及到, 再关联右表.

用途

似乎没啥用. Left outer join 右表 的目的肯定是要从表中获取数据呀.

唯一的作用, 动态SQL时, 会根据动态设定的字段来确定读取的数据的条目数.

仔细思考了该语法的业务用途

这个语句可以让SQL根据字段的需求自行判断返回的结果集数量.

比如只获取左表内容(抬头表). 则返回抬头一行

如果包含了明细表字段, 则返回明细多行,如果没有明细,返回抬头一行

扩展

如果我们关联的右表有多条记录,结果集中包含右表的字段,但是只想显示一条.(第一眼误会MANY TO ONE 子句含义,想达成的目的)

此时针对不同的考虑,应用不同的处理方式

_**01** _

**获取任意一个工厂**

考虑使用 SELECT MATNR,MAX( WERKS) 或 MIN(WERKS).

select a.matnr,max( c.werks ) from mara as a

left outer join marc as c on c.mandt = a.mandt and c.matnr = a.matnr

where a.matnr = 'TEST20210203/1'

group by a.matnr

_**02** _

**多个工厂的采购组一样**

考虑使用 SELECT DISTICT MATNR,EKGRP 但这样做的风险在于, 一旦出现地点的采购组不通的情况, 结果集就会返回多条记录了

select distinct a.matnr,c.ekgrp from mara as a

left outer join marc as c on c.mandt = a.mandt and c.matnr = a.matnr

where a.matnr = 'TEST20210203/1'

_**03** _

**获取最大工厂号的采购组**

则需要使用 rank() 及嵌套SQL 语句了

select * from

( select a.matnr,c.ekgrp ,

rank( ) over( partition by a.matnr order by werks desc ) as zrank

from mara as a

left outer join marc as c on c.mandt = a.mandt and c.matnr = a.matnr

)

where matnr = 'TEST20210203/1' and zrank = 1

如果时最小工厂号,则去掉werks 后面的 desc(表示倒排序)

总结

LEFT OUTER JOIN 中的 MANY TO ONE 子句是动态读取抬头表和明细表的SQL语句的一个较为简洁的表达方式.

无需根据查询的字段 动态设置 FROM 子句内容.

用 LEFT OUTER MANY TO ONE 语句关联相关表,

根据字段所在的表,数据库系统自动判断是否需要关联右表(这个说法不一定准确,仅从测试的表现判断的,实际上数据库可能使用其它机制).

ABAP技巧与实战

关于作者:ABAP技巧与实战

企业信息化与 SAP 技术顾问,长期专注 SAP ABAP、FI/CO、MM、SD 等模块的技术分享与实战经验总结。查看更多介绍

来源说明:本文内容由「ABAP基础知识不一样的leftjoin.md」整理生成,仅用于内部技术分享与学习交流。