【问题标题】:LEFT JOIN ON COALESCE(a, b, c) - very strange behaviorLEFT JOIN ON COALESCE(a, b, c) - 非常奇怪的行为
【发布时间】:2014-11-17 23:17:14
【问题描述】:

我的查询遇到了非常奇怪的行为,我浪费了很多时间来了解导致它的原因。所以我请求你的帮助。

SELECT count(*) FROM main_table
LEFT JOIN front_table ON front_table.pk = main_table.fk_front_table
LEFT JOIN info_table ON info_table.pk = front_table.fk_info_table
LEFT JOIN key_table ON key_table.pk = COALESCE(info_table.fk_key_table, front_table.fk_key_table_1, front_table.fk_key_table_2)
LEFT JOIN side_table ON side_table.fk_front_table = front_table.pk
WHERE side_table.pk = (SELECT MAX(pk) FROM side_table WHERE fk_front_table = front_table.pk)
OR side_table.pk IS NULL

看起来像一个简单的连接查询,使用合并,我以前使用过这种技术(不是太多次)并且效果很好。

在这个查询中,我从来没有得到 side_table.pk 的空值。如果我删除了 coalesce 或者只是不使用 key_table,那么查询会返回包含许多 null side_table.pk 的行,但是如果我添加了 coalesce join,我将无法获得这些 null。

好像key_table和side_table没有什么共同点,结果却很诡异。

另外,当我不使用 side_table 和 WHERE 子句时,count(*) 结果与合并和没有不同,但我看不到任何缺失的行中的模式,这似乎是随机的!

真实查询:

SELECT ECHANGE.EXC_AUTO_KEY, STOCK_RESERVATIONS.STR_AUTO_KEY FROM EXCHANGE
LEFT JOIN WO_BOM ON WO_BOM.WOB_AUTO_KEY = EXCHANGE.WOB_AUTO_KEY
LEFT JOIN VIEW_WO_SUB ON VIEW_WO_SUB.WOO_AUTO_KEY = WO_BOM.WOO_AUTO_KEY
LEFT JOIN STOCK stock3 ON stock3.STM_AUTO_KEY = EXCHANGE.STM_AUTO_KEY
LEFT JOIN STOCK stock2 ON stock2.STM_AUTO_KEY = EXCHANGE.ORIG_STM
LEFT JOIN CONSIGNMENT_CODES con2 ON con2.CNC_AUTO_KEY = stock2.CNC_AUTO_KEY
LEFT JOIN CONSIGNMENT_CODES con3 ON con3.CNC_AUTO_KEY = stock3.CNC_AUTO_KEY
LEFT JOIN CI_UTL ON CI_UTL.CUT_AUTO_KEY = EXCHANGE.CUT_AUTO_KEY
LEFT JOIN PART_CONDITION_CODES pcc2 ON pcc2.PCC_AUTO_KEY = stock2.PCC_AUTO_KEY
LEFT JOIN PART_CONDITION_CODES pcc3 ON pcc3.PCC_AUTO_KEY = stock3.PCC_AUTO_KEY
LEFT JOIN STOCK_RESERVATIONS ON STOCK_RESERVATIONS.STM_AUTO_KEY = stock3.STM_AUTO_KEY
LEFT JOIN WAREHOUSE wh2 ON wh2.WHS_AUTO_KEY = stock2.WHS_ORIGINAL
LEFT JOIN SM_HISTORY ON (SM_HISTORY.STM_AUTO_KEY = EXCHANGE.ORIG_STM AND SM_HISTORY.WOB_REF = EXCHANGE.WOB_AUTO_KEY)
LEFT JOIN RC_DETAIL ON stock3.RCD_AUTO_KEY = RC_DETAIL.RCD_AUTO_KEY
LEFT JOIN RC_HEADER ON RC_HEADER.RCH_AUTO_KEY = RC_DETAIL.RCH_AUTO_KEY
LEFT JOIN WAREHOUSE wh3 ON wh3.WHS_AUTO_KEY = COALESCE(RC_DETAIL.WHS_AUTO_KEY, stock3.WHS_ORIGINAL, stock3.WHS_AUTO_KEY)
WHERE STOCK_RESERVATIONS.STR_AUTO_KEY = (SELECT MAX(STR_AUTO_KEY) FROM STOCK_RESERVATIONS WHERE STM_AUTO_KEY = stock3.STM_AUTO_KEY)
OR STOCK_RESERVATIONS.STR_AUTO_KEY IS NULL

删除 LEFT JOIN WAREHOUSE wh3 为我提供了具有大量 NULL STR_AUTO_KEY 的唯一 EXC_AUTO_KEY 值,而离开此行将删除所有 NULL STR_AUTO_KEY。

我重新创建了具有相同结构的数字的简单表,并且查询工作没有任何问题 o.0

【问题讨论】:

  • 我怀疑您需要通过一些示例数据来阐明问题,这些数据表明您认为出了什么问题。
  • 我假设您的意思是,如果没有 where 子句中的条件,您将永远无法获得 NULL 值。
  • 请在代码问题中给出minimal reproducible example--剪切&粘贴&可运行代码;具有期望和实际输出的示例输入(包括逐字错误消息);标签和明确的规范和解释。这包括您可以提供的最少代码,即您显示的代码可以通过您显示的代码扩展为不正常。 (调试基础。) PS 显然这里有非最小代码/数据。

标签: sql oracle left-join coalesce


【解决方案1】:

我感觉COALESCE 正在充当连接表的REQUIRED 标志,因此将LEFT JOIN 拍摄为INNER JOIN

试试这个:

SELECT COUNT(*) 
FROM main_table
  LEFT JOIN front_table ON front_table.pk = main_table.fk_front_table
  LEFT JOIN info_table ON info_table.pk = front_table.fk_info_table
  LEFT JOIN key_table ON key_table.pk = NVL(info_table.fk_key_table, NVL(front_table.fk_key_table_1, front_table.fk_key_table_2))
  LEFT JOIN (SELECT fk_, MAX(pk) as pk FROM side_table GROUP BY fk_) st ON st.fk_ = front_table.pk

NVL 的行为可能完全相同...

【讨论】:

  • 感谢您的回答,但 NVL 的行为相同,也尝试过。很快我还有很多话要说,试着获取数据。
  • 只是好奇你为什么需要COUNT(*) 那个查询。我想这是对 SO 的修改查询,但就目前而言,COUNT 是解决此问题的问题。最好能看到原始查询
  • 我用这种结构重新创建了带有数字的简单表格,这个查询工作得很好,所以我猜数据中有什么东西?我添加了原始查询,非常不可读,但应该是草稿:)
  • 到目前为止,我得到了这个:如果我将 coalesce join 放在 side_table join 之前,它包含在 where 子查询中 - 一切正常。如果我将 OR 子句拆分为两个不同的子查询,它们都会分别给出正确的结果。如果我不在 coalesce 中使用 info_table - 它可以工作。
  • 很抱歉我无法跟进此事。这是一个非常有趣的主题,所以如果你找到任何解决方案,请分享你的解决方案,但是我没有必要的时间来帮助你解决这个问题,因为我一直很忙。
【解决方案2】:

我知道问题出在哪里(虽然不完全):原始查询中的第 3 行有一个 LEFT JOIN VIEW_WO_SUB。它会导致此查询以一种奇怪的方式运行。

当我用包含我需要的信息的另一个表替换视图时,查询开始返回正确的结果。

基本上,使用此视图连接,NVL、COALESCE 或 CASE 连接与某些参数的组合不能与 WHERE 子查询中的 OR 子句一起工作,其余一切都很好。虽然,我可以让查询与此视图连接一起工作,但通过更改连接表的顺序,我必须将参与 where 子查询的表放在底部。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-25
    • 2015-06-23
    • 2020-07-29
    • 2019-07-21
    • 2021-12-07
    • 2016-03-13
    • 2011-03-01
    • 2016-05-11
    相关资源
    最近更新 更多