sql - 首先在最低级别/最详细的字段值上加入查找表
问题描述
我有两个表,我试图基于 SQL Server 2014 中的单个字段离开联接,但问题是这个单个字段包含一个与主表中不同列中出现的四个“级别”之一相关的值. 该SalesOrg
字段也是键的一部分,因为在事务表和查找表中都可以有多个销售组织。
这是主要的事务表:
SalesOrg PHLevel1 PHLevel2 PHLevel3 PHLevel4 SalesQty
-----------------------------------------------------------------------
AB1 Z000 Y000 X000 V000 20
AB1 Z000 Y000 X000 V001 30
AB1 Z001 Y000 X001 V001 10
AB1 Z001 Y001 X000 V003 45
AB1 Z001 Y001 X000 V004 48
AB1 Z002 Y003 X002 V005 67
这是我试图加入事务表的查找表:
SalesOrg PH PHLevel SalesRep
--------------------------------------------------
AB1 <null> 0 Mr. Pink
AB1 Z000 1 Mr. White
AB1 Z001 1 Mr. White
AB1 Z001Y000 2 Mr. Orange
AB1 Z001Y001 2 Mr. Orange
AB1 Z001Y001X000 3 Mr. Blonde
所以应该发生的是“最低”(即最高PHLevel
,3
)应该首先匹配,即:
SalesOrg PHLevel1 PHLevel2 PHLevel3 PHLevel4 SalesQty SalesRep
---------------------------------------------------------------------------------
AB1 Z000 Y000 X000 V000 20
AB1 Z000 Y000 X000 V001 30
AB1 Z001 Y000 X001 V001 10
AB1 Z001 Y001 X000 V003 45 Mr. Blonde
AB1 Z001 Y001 X000 V004 48 Mr. Blonde
AB1 Z002 Y003 X002 V005 67
然后我们需要匹配尚未使用级别 3 匹配的级别 2:
SalesOrg PHLevel1 PHLevel2 PHLevel3 PHLevel4 SalesQty SalesRep
---------------------------------------------------------------------------------
AB1 Z000 Y000 X000 V000 20
AB1 Z000 Y000 X000 V001 30
AB1 Z001 Y000 X001 V001 10 Mr. Orange
AB1 Z001 Y001 X000 V003 45 Mr. Blonde
AB1 Z001 Y001 X000 V004 48 Mr. Blonde
AB1 Z002 Y003 X002 V005 67
然后我们需要匹配尚未使用级别 2 或 3 匹配的级别 1:
SalesOrg PHLevel1 PHLevel2 PHLevel3 PHLevel4 SalesQty SalesRep
---------------------------------------------------------------------------------
AB1 Z000 Y000 X000 V000 20 Mr. White
AB1 Z000 Y000 X000 V001 30 Mr. White
AB1 Z001 Y000 X001 V001 10 Mr. Orange
AB1 Z001 Y001 X000 V003 45 Mr. Blonde
AB1 Z001 Y001 X000 V004 48 Mr. Blonde
AB1 Z002 Y003 X002 V005 67
最后,对于任何剩余的项目,我们需要检查级别 0,这是“不匹配”条目的默认值:
SalesOrg PHLevel1 PHLevel2 PHLevel3 PHLevel4 SalesQty SalesRep
---------------------------------------------------------------------------------
AB1 Z000 Y000 X000 V000 20 Mr. White
AB1 Z000 Y000 X000 V001 30 Mr. White
AB1 Z001 Y000 X001 V001 10 Mr. Orange
AB1 Z001 Y001 X000 V003 45 Mr. Blonde
AB1 Z001 Y001 X000 V004 48 Mr. Blonde
AB1 Z002 Y003 X002 V005 67 Mr. Pink
如果在事务表中创建连接字段以更容易匹配查找表,则没有问题。
我不确定扩展查找表是否有利,以便该字段包含“完全限定”的值(PH
即PH
始终包含///PHLevel1
值PHLevel2
,例如),但这可能会使查找表变得巨大,然后可能减慢连接(因为事务表可能包含一百万行)。PHLevel3
PHLevel4
Z001Y000X001V001
我不知道如何开始,因为我已经看到了其他带有层次结构的示例,但是查找表并不完全是一个层次结构——请问在 SQL 中有什么优雅的解决方案吗?
解决方案
当我看到这样的代码时,我有点焦虑,但在您的情况下,它似乎反映了真正的需求,假设您无法更改表的底层结构:
select t.*,
SalesRep = coalesce(l4.SalesRep, l3.SalesRep, l2.SalesRep, l1.SalesRep, l0.SalesRep)
from @transactionals t
left join @lookup l4 on t.SalesOrg = l4.SalesOrg and l4.PH = t.PHLevel1 + t.PHLevel2 + t.PHLevel3 + t.PHLevel4
left join @lookup l3 on t.SalesOrg = l3.SalesOrg and l3.PH = t.PHLevel1 + t.PHLevel2 + t.PHLevel3
left join @lookup l2 on t.SalesOrg = l2.SalesOrg and l2.PH = t.PHLevel1 + t.PHLevel2
left join @lookup l1 on t.SalesOrg = l1.SalesOrg and l1.PH = t.PHLevel1
left join @lookup l0 on t.SalesOrg = l0.SalesOrg and l0.PH is null
经过多一点考虑,我认为另一种策略会奏效。正如您所怀疑的,您可以连接事务表中的级别。然后你可以根据like 语句进行匹配。当然,这会让你得到太多的匹配,所以你使用一个窗口函数来找到匹配之间的最大 phLevel。然后查询 phLevel 等于最大值的位置。
with
leadMatches as (
select t.*,
l.SalesRep,
l.PHLevel,
maxPhLevel = max(l.phLevel) over (partition by ap.ph)
from @transactionals t
cross apply (select PH = PHLevel1 + PHLevel2 + PHLevel3 + PHLevel4) ap
join @lookup l on t.SalesOrg = l.SalesOrg and ap.ph like isnull(l.ph,'') + '%'
)
select m.SalesOrg, m.PHLevel1, m.PHLevel2, m.PHLevel3, m.PHLevel4,
m.SalesQty, m.SalesRep
from leadMatches m
where PHLevel = maxPhLevel
推荐阅读
- python - 如何修复'AttributeError:'dict'对象没有属性'code'
- python - Python Turtle,更改可见部分
- c# - 在 C# 中使用 Tesseract
- java - 通过 DNS 检查互联网连接
- node.js - webpack 输出丢弃依赖项
- jenkins - Jenkins插件动态填充下拉
- clojure - clojure-spec:无法正确获取函数的后置条件
- php - 自定义 WooCommerce 登录表单用户字段
- python - Pandas Dataframe 的多处理写入 Excel 工作表
- php - 从nodemcu发布数据时如何解决编码错误