具有条件列匹配的内部/左外部连接

Inner / Left outer Join with conditional column matching

我需要一些关于 left outer join/inner join 的帮助,条件如下;

select a.val1,a.val2,b.val1,b.val2,..
from tableA a 
inner join tableB b 
on (if a.val1<>0 then a.val1=b.val1
  and if a.val2<>0 then a.val2=b.val2
  and if a.val3<>0 then a.val3=b.val3
  and if a.val4<>0 then a.val4=b.val4)
where a.description='ABC'

我只想根据 if value 不为零 null 的条件匹配某些列

如有任何帮助,我们将不胜感激。 我已经尝试过 CASE WHEN 等等,但没有成功。 请给我提供正确的语法来匹配上面的例子,因为我不是这方面的专家。 谢谢

ZEE

感谢您的回复 Hogan,我知道您的示例很好,但对我来说没用,因为 我对场景缺乏解释。

请在此处查看示例数据;

主表
MakeID|Make---|ModelID|Model|ColorID|Color---|SizeID|Size|Mat
1 |马球 | 1 | LT | 1 |黑色 | 1 | S |婴儿床
1 |马球 | 1 | LT | 1 |黑色| 2 | M |极化
1 |马球 | 2 | XT| 2 |红色| 3 | S |波尔
2 |差距| 3 |尼克 | 3 |黑色| 4 | S |波尔科特
2 |差距| 4 |路劲 | 4 |红色| 5 | M |羊毛
3 |箭头| 5 | MM | 5 |黑色| 6 |大号 |羊毛
3 |箭头| 5 | MM | 6 |白色| 7 | XL |波尔
3 |箭头| 6 | LM | 7 |黑色| 8 | S |婴儿床
4 |之字形| 7 |汞 | 7 |绿色| 9 | S |波尔科特
4 |之字形| 7 |汞 | 7 |绿色| 10 | M |羊毛
映射表
MapID|ItemID|MakeMatch|ModelMatch|ColorMatch|SizeMatch|材质
1 |字母表 | 1 | 1 | 1 | 1 |婴儿床
2 |字母表 | 1 | 2 | 0 | 0 |波尔
3 |字母表 | 3 | 6 | 0 | 0 |羊毛
4 |字母表| 4 | 7 | 7 | 0 |波尔科特
5 |XY | .. | .. | .. | ..|..
6 |XY | .. | .. | .. | ..|..
7 |XY | .. | .. | .. | ..|..

我希望得到的结果: 以下之一;

MapID|Make--|Model|Color--|Size|Mat
1 |Polo |LT |黑色 |S |婴儿床
2 |Polo |XT |null |null|Pol
3 |Arrow |LM |null |null|羊毛
4 |Zig |HG |Green |null|PolCot

或以下;

MapID|Concat-字段
1 |Polo-LT-Black-S-Cot
2 |Polo-XT--波尔
3 |Arrow-LM--羊毛
4 |Zig-HG-Green--PolCot

使用 maptable,我需要提取由 itemid='ABC' 组成的记录,并从 MainTable 中获取每个 iD 的匹配值,如 MakeMatch、ModelMatch、ColorMatch、SizeMatch。它始终按 MakeMatch,ModelMatch,ColorMatch,SizeMatch 的顺序填充值。 MakeMatch 始终会被填充,但其他字段可以为零。例如。如果 ColorMatch 为零,其父项 MakeMatch、ModelMatch 将始终被填充。但如果 ColorMatch 为零,SizeMatch 也将为零。

所以我尝试了不同的方法来使用内部连接和左外部连接进行拉取,但都无济于事。 能否请您告诉我什么是获得此处显示的预期结果的最佳方法。

注意:由于包含未格式化的代码而无法发布。.逐节尝试..
谢谢霍根, 感谢您的回复。你提供的代码,产生了我想要的结果, 除了我必须包括 select distinct

SELECT distinct M.MapID, Model.Make, Model.Model, Color.Color, Size.Size, M.Material
FROM MapTable AS M
JOIN (SELECT MakeID, Make 
  FROM MainTable 
  GROUP BY MakeID, Make) AS Make ON M.MakeMatch = Make.MakeID
LEFT JOIN MainTable Model ON M.MakeMatch = Model.MakeID AND M.ModelMatch = Model.ModelID
LEFT JOIN MainTable Color ON M.MakeMatch = Color.MakeID AND M.ColorMatch = Color.ColorID
LEFT JOIN MainTable Size ON M.MakeMatch = Size.MakeID AND M.SizeMatch = Size.SizeID
where M.ItemID = 'ABC'

但是,在一种情况下,结果略有不同。 当我如下向 mapTable 添加了一条记录时

7 |美国广播公司| 2 | 0 | 0 | 0 |羊毛

添加这条记录后,结果如下;

MapID|Make--|Model|Color--|Size|Mat
1 |Polo |LT |黑色 |S |婴儿床
2 |Polo |XT |null |null|Pol
3 |Arrow |LM |null |null|羊毛
4 |Zig |HG |Green |null|PolCot
7 |null |null |null |null|羊毛

最后7条记录没有拉Make

仅供参考,我已经尝试了以下给出正确结果的代码。但我知道这不是一种有效的方法。 如果您可以查看下面的代码并提出更好的编码建议,我们将不胜感激。

select Maptable.mapid ,concat(
(select top 1 make from MainTable where MainTable.makeid=MapTable.MakeMatch)+'--->', 
(select top 1 model from MainTable where MainTable.modelid=maptable.ModelMatch)+'--->', 
(select top 1 size from MainTable where MainTable.SizeID=MapTable.SizeMatch)+'--->',
(select top 1 Color from MainTable where MainTable.ColorID=MapTable.ColorMatch),
maptable.material) as Selection
from maptable  where maptable.itemid = 'ABC' 

这个产生了下面的结果,这是我需要的。


    地图编号 |细节
    1 Polo--->LT--->S--->Black-->Cot
    2 马球--->XT--->波尔
    3 箭头--->LM--->羊毛
    4 Zig--->HG--->Black-->PolCot
    7 Gap--->羊毛

再一次,如果你能为我提供更高效的编码,我将不胜感激。

好的,现在我看到了你的示例数据,我可以给你正确的 SQL:

SELECT M.MapID,  Make.Make, Model.Model, Color.Color, Size.Size, M.Material
FROM MapTable AS M
JOIN (SELECT MakeID, Make 
      FROM MainTable 
      GROUP BY MakeID, Make) AS Make ON M.MakeMatch = Make.MakeID
LEFT JOIN MainTable Model ON M.MakeMatch = Model.MakeID AND M.ModelMatch = Model.ModelID
LEFT JOIN MainTable Color ON M.MakeMatch = Color.MakeID AND M.ColorMatch = Color.ColorID
LEFT JOIN MainTable Size ON M.MakeMatch = Size.MakeID AND M.SizeMatch = Size.SizeID

不需要 case 语句——只需简单的左连接。


原回答

使用这样的 case 语句:

select a.val1,a.val2,b.val1,b.val2,..
from tableA a 
inner join tableB b 
on  CASE WHEN ISNULL(a.val1,0)=0 then b.val1 ELSE a.val1 END =b.val1
and CASE WHEN ISNULL(a.val2,0)=0 then b.val2 ELSE a.val2 END =b.val2
and CASE WHEN ISNULL(a.val3,0)=0 then b.val3 ELSE a.val3 END =b.val3
and CASE WHEN ISNULL(a.val4,0)=0 then b.val4 ELSE a.val4 END =b.val4
and (ISNULL(a.val1,0) <> 0 OR ISNULL(a.val2,0) <> 0 
  OR ISNULL(a.val3,0) <> 0 OR ISNULL(a.val4,0) <>0)
where a.description='ABC'