SQL NOT EXISTS 子查询未按预期运行

Posted

技术标签:

【中文标题】SQL NOT EXISTS 子查询未按预期运行【英文标题】:SQL NOT EXISTS sub query not functioning as expected 【发布时间】:2018-11-14 01:49:50 【问题描述】:

我有一个问题,我使用查询根据文章的前置时间过滤我的结果。对我来说令人困惑的部分是其中的一个子部分,我需要根据交货时间和原产国过滤某些文章。我试图在WHERE 旁边使用NOT EXISTSstatement 来做到这一点,但结果似乎不是我所期望的。例如,所有原产国为洪都拉斯且交货时间为 90 的文章不应返回 so_conf_del_date 为 2/15/19 之后的任何结果......但是在结果中,我得到了许多日期的结果,这些结果应该是 3 月被排除在我能看到的范围之外。以为我会对它有不同的看法,因为我真的不使用不存在大量。谢谢。

更新:从 NOT EXISTS 更改为 NOT IN 并更新了相关性。另请注意,子查询完全按照它应该执行的方式执行,因此不确定为什么我得到的结果超出范围

查询已更新:

/* What to do about multiple COO's in ONE RANGE? ...join on order ORDER_ITEM.SEASONAL_INDICATOR? */
/* Use CASE WHEN in subquery to JOIN outerquery on vw_order_item.seasonal_indicator = OneRange_NAM.SEASON */
/* Assumption is being made that 'seasonal indicator' in vw_order_item would align with 'season' and thus COO in OneRange */
/* Added Date/LeadTime Parameters */
/* Use 'Planned Delivery Time'...this includes lead time and delivery time? */
/* Right join to ONE RANGE */
/* ARUN has no fully unallocated quantities - YES IT DOES */
/* 11/12/18 - replaced RDD with CDD */

SELECT kd.business_segment_desc, 
       q0.plant_code,
       q0.req_cat AS 'requirement_category',
       m.[department], 
       q0.commission_code_id,
       aa.LeadTime,
       q0.so_conf_del_date, 
       q0.valid_to_date,
       q0.sales_order_number, 
       q0.sales_order_item_number,
       q0.sold_to, 
       q0.bill_to,
       m.working_number,
       q0.material,
       m.[description],
       q0.open_quantity,
       q0.allocated_quantity,
       q0.unallocated_quantity,
       q0.percent_unallocated,
       aa.ActivationStatus AS 'global status',
       m.ib_lock,
       o.country_of_origin

FROM   pdx_sap_user..vw_mm_material m
JOIN   pdx_sap_user..vw_kd_business_segment kd ON m.business_segment_code = kd.business_segment_code
JOIN   asagdwpdx_prod..ArticleNumbers aa ON m.material = aa.ArticleNumber
JOIN   adi_user_maintained..VW_ONERange_NAM o ON     m.material = o.article 
                                              AND    aa.ArticleNumber = o.Article
JOIN

(SELECT i.plant_code, 
       h.commission_code_id, 
       a.so_conf_del_date,
       h.valid_to_date,
       i.sales_order_number, 
       i.sales_order_item_number,
       h.sold_to,
       h.bill_to,
       i.material,
       i.open_quantity,
      ((i.open_quantity) - SUM(a.quantity)) AS 'allocated_quantity',
     SUM(a.quantity) AS 'unallocated_quantity',
       a.req_cat,
       ROUND(SUM(a.quantity)/(i.open_quantity),2) AS 'percent_unallocated',
       SUM(a.quantity) AS 'arun_allocated_qty',
       CASE 
         WHEN i.seasonal_indicator = '18S' 
         THEN 'SS2018' 
         WHEN i.seasonal_indicator = '18F'
         THEN 'FW2018'
         WHEN i.seasonal_indicator = '19S' 
         THEN 'SS2019' 
         WHEN i.seasonal_indicator = '19F' 
         THEN 'FW2019'
         ELSE 'NO SEASON'
       END AS 'seasonal_indicator'

FROM   pdx_sap_user..vw_order_item i 
JOIN  pdx_sap_user..vw_order_header h ON i.sales_order_number = h.sales_order_number 
JOIN   pdx_sap_user..vw_arun_norm_new a ON i.sales_order_number = a.sales_order_number 
AND    i.sales_order_item_number = a.sales_order_item_number


WHERE  i.open_quantity > 0
AND    h.commission_code_id = 'B'
AND    a.stock_type = 'A'

GROUP BY i.plant_code, 
         h.commission_code_id, 
         a.so_conf_del_date,
         h.valid_to_date,
         i.sales_order_number, 
         i.sales_order_item_number,
         h.sold_to,
         h.bill_to,
         i.material,
         i.open_quantity,
         a.req_cat,
         i.unallocated_quantity,
         i.seasonal_indicator

HAVING SUM((a.quantity)/i.open_quantity) > .5) q0 ON m.material = q0.material 
                                                  AND q0.seasonal_indicator = o.season

WHERE    aa.LeadTime = '30'
AND      q0.so_conf_del_date < '01/15/2019'
OR       aa.LeadTime = '45'
AND      q0.so_conf_del_date < '02/01/2019'
OR       aa.LeadTime = '60'
AND      q0.so_conf_del_date < '02/15/2019'
OR       aa.LeadTime = '75'
AND      q0.so_conf_del_date < '03/01/2019'
OR       aa.LeadTime = '90'
AND      q0.so_conf_del_date < '03/15/2019'
OR       aa.LeadTime = '105'
AND      q0.so_conf_del_date < '04/01/2019'
OR       aa.LeadTime = '120'
AND      q0.so_conf_del_date < '04/15/2019'
OR       aa.LeadTime = '135'
AND      q0.so_conf_del_date < '05/01/2019'

AND      q0.sales_order_number NOT IN ( SELECT   q01.sales_order_number

                                        FROM   pdx_sap_user..vw_order_item q01
                                        JOIN   pdx_sap_user..vw_arun_norm_new a1 ON q01.sales_order_number = a1.sales_order_number 
                                        AND    q01.sales_order_item_number = a1.sales_order_item_number
                                        JOIN   asagdwpdx_prod..ArticleNumbers aa1 ON q01.material = aa1.ArticleNumber
                                        JOIN   adi_user_maintained..VW_ONERange_NAM o1 ON q01.material = o1.article 

WHERE  
(
aa1.LeadTime = '30'
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '12/15/2018'
)
OR     
(
aa1.LeadTime = '45' 
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '01/01/2019'
)
OR     
(
aa1.LeadTime = '60' 
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '01/15/2019'
)
OR     
(
aa1.LeadTime = '75' 
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '02/01/2019'
)
OR     
(
aa1.LeadTime = '90' 
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '02/15/2019'
)
OR     
(
aa1.LeadTime = '90' 
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '03/01/2019'
)
OR     
(
aa1.LeadTime = '105' 
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '03/15/2019'
)
AND    q0.sales_order_number = q01.sales_order_number
AND    aa.LeadTime = aa1.LeadTime
AND    q0.so_conf_del_date = a1.so_conf_del_date
AND    o.Country_of_Origin = o1.Country_of_Origin)

GROUP BY kd.business_segment_desc, 
         q0.plant_code,
         q0.req_cat,
         m.[department], 
         q0.commission_code_id,
         aa.LeadTime,
         q0.so_conf_del_date, 
         q0.valid_to_date,
         q0.sales_order_number, 
         q0.sales_order_item_number,
         q0.sold_to, 
         q0.bill_to,
         m.working_number,
         q0.material,
         m.[description],
         q0.open_quantity,
         q0.allocated_quantity,
         q0.unallocated_quantity,
         q0.percent_unallocated,
         aa.ActivationStatus,
         m.ib_lock,
         o.country_of_origin

ORDER BY q0.sales_order_number DESC; 

工作版本:

/* What to do about multiple COO's in ONE RANGE? ...join on order ORDER_ITEM.SEASONAL_INDICATOR? */
/* Use CASE WHEN in subquery to JOIN outerquery on vw_order_item.seasonal_indicator = OneRange_NAM.SEASON */
/* Assumption is being made that 'seasonal indicator' in vw_order_item would align with 'season' and thus COO in OneRange */
/* Added Date/LeadTime Parameters */
/* Use 'Planned Delivery Time'...this includes lead time and delivery time? */
/* Right join to ONE RANGE */
/* ARUN has no fully unallocated quantities - YES IT DOES */
/* 11/12/18 - replaced RDD with CDD */

SELECT kd.business_segment_desc, 
       q0.plant_code,
       q0.req_cat AS 'requirement_category',
       m.[department], 
       q0.commission_code_id,
       aa.LeadTime,
       q0.so_conf_del_date, 
       q0.valid_to_date,
       q0.sales_order_number, 
       q0.sales_order_item_number,
       q0.sold_to, 
       q0.bill_to,
       m.working_number,
       q0.material,
       m.[description],
       q0.open_quantity,
       q0.allocated_quantity,
       q0.unallocated_quantity,
       q0.percent_unallocated,
       aa.ActivationStatus AS 'global status',
       m.ib_lock,
       o.country_of_origin

FROM   pdx_sap_user..vw_mm_material m
JOIN   pdx_sap_user..vw_kd_business_segment kd ON m.business_segment_code = kd.business_segment_code
JOIN   asagdwpdx_prod..ArticleNumbers aa ON m.material = aa.ArticleNumber
JOIN   adi_user_maintained..VW_ONERange_NAM o ON     m.material = o.article 
                                              AND    aa.ArticleNumber = o.Article
JOIN

(SELECT i.plant_code, 
       h.commission_code_id, 
       a.so_conf_del_date,
       h.valid_to_date,
       i.sales_order_number, 
       i.sales_order_item_number,
       h.sold_to,
       h.bill_to,
       i.material,
       i.open_quantity,
      ((i.open_quantity) - SUM(a.quantity)) AS 'allocated_quantity',
     SUM(a.quantity) AS 'unallocated_quantity',
       a.req_cat,
       ROUND(SUM(a.quantity)/(i.open_quantity),2) AS 'percent_unallocated',
       SUM(a.quantity) AS 'arun_allocated_qty',
       CASE 
         WHEN i.seasonal_indicator = '18S' 
         THEN 'SS2018' 
         WHEN i.seasonal_indicator = '18F'
         THEN 'FW2018'
         WHEN i.seasonal_indicator = '19S' 
         THEN 'SS2019' 
         WHEN i.seasonal_indicator = '19F' 
         THEN 'FW2019'
         ELSE 'NO SEASON'
       END AS 'seasonal_indicator'

FROM   pdx_sap_user..vw_order_item i 
JOIN  pdx_sap_user..vw_order_header h ON i.sales_order_number = h.sales_order_number 
JOIN   pdx_sap_user..vw_arun_norm_new a ON i.sales_order_number = a.sales_order_number 
AND    i.sales_order_item_number = a.sales_order_item_number


WHERE  i.open_quantity > 0
AND    h.commission_code_id = 'B'
AND    a.stock_type = 'A'
AND    i.sales_order_number NOT IN (SELECT   q01.sales_order_number

                                        FROM   pdx_sap_user..vw_order_item q01
                                        JOIN   pdx_sap_user..vw_arun_norm_new a1 ON q01.sales_order_number = a1.sales_order_number 
                                        AND    q01.sales_order_item_number = a1.sales_order_item_number
                                        JOIN   asagdwpdx_prod..ArticleNumbers aa1 ON q01.material = aa1.ArticleNumber
                                        JOIN   adi_user_maintained..VW_ONERange_NAM o1 ON q01.material = o1.article 

WHERE  
(
aa1.LeadTime = '30'
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '12/15/2018'
)
OR     
(
aa1.LeadTime = '45' 
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '01/01/2019'
)
OR     
(
aa1.LeadTime = '60' 
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '01/15/2019'
)
OR     
(
aa1.LeadTime = '75' 
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '02/01/2019'
)
OR     
(
aa1.LeadTime = '90' 
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '02/15/2019'
)
OR     
(
aa1.LeadTime = '90' 
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '03/01/2019'
)
OR     
(
aa1.LeadTime = '105' 
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '03/15/2019'
)
AND    q01.sales_order_number = i.sales_order_number)

GROUP BY i.plant_code, 
         h.commission_code_id, 
         a.so_conf_del_date,
         h.valid_to_date,
         i.sales_order_number, 
         i.sales_order_item_number,
         h.sold_to,
         h.bill_to,
         i.material,
         i.open_quantity,
         a.req_cat,
         i.unallocated_quantity,
         i.seasonal_indicator

HAVING SUM((a.quantity)/i.open_quantity) > .5) q0 ON m.material = q0.material 
                                                  AND q0.seasonal_indicator = o.season

WHERE    aa.LeadTime = '30'
AND      q0.so_conf_del_date < '01/15/2019'
OR       aa.LeadTime = '45'
AND      q0.so_conf_del_date < '02/01/2019'
OR       aa.LeadTime = '60'
AND      q0.so_conf_del_date < '02/15/2019'
OR       aa.LeadTime = '75'
AND      q0.so_conf_del_date < '03/01/2019'
OR       aa.LeadTime = '90'
AND      q0.so_conf_del_date < '03/15/2019'
OR       aa.LeadTime = '105'
AND      q0.so_conf_del_date < '04/01/2019'
OR       aa.LeadTime = '120'
AND      q0.so_conf_del_date < '04/15/2019'
OR       aa.LeadTime = '135'
AND      q0.so_conf_del_date < '05/01/2019'

GROUP BY kd.business_segment_desc, 
         q0.plant_code,
         q0.req_cat,
         m.[department], 
         q0.commission_code_id,
         aa.LeadTime,
         q0.so_conf_del_date, 
         q0.valid_to_date,
         q0.sales_order_number, 
         q0.sales_order_item_number,
         q0.sold_to, 
         q0.bill_to,
         m.working_number,
         q0.material,
         m.[description],
         q0.open_quantity,
         q0.allocated_quantity,
         q0.unallocated_quantity,
         q0.percent_unallocated,
         aa.ActivationStatus,
         m.ib_lock,
         o.country_of_origin

ORDER BY q0.sales_order_number DESC

【问题讨论】:

猜一猜......你需要更多的括号来正确定义OR布尔表达式。你有一个OR(或者可能很多),它使整个布尔表达式短路。 似乎很奇怪,因为在所有其他行上执行相同操作的外部语句工作完美......想知道它是否与 IN 语句有关,或者它如何连接到外部查询? 【参考方案1】:

您的 OR 短路。比如看这块:

SELECT *
FROM Table
WHERE  aa1.LeadTime = '30'
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '12/15/2018'
OR     aa1.LeadTime = '45' 

返回所有带有aa1.LeadTime = '45' 的记录,无论其他条件如何。

我猜你的意思是:

WHERE  
(
aa1.LeadTime = '30'
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '12/15/2018'
)
OR     
(
aa1.LeadTime = '45' 
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '01/01/2019'
)
OR     
(
aa1.LeadTime = '60' 
AND    o1.country_of_origin IN ('EL SALVADOR','HONDURAS','MEXICO','U S A' ,'GUATEMALA')
AND    a1.so_conf_del_date > '01/15/2019'
)
....
....

这是一个非常不同的表达方式。

【讨论】:

啊,感谢您的澄清!出于某种原因,我假设执行顺序在每个 OR 处重新开始,我将试一试! 仍在返回范围之外的结果 - 例如,提前期 45 表示返回日期早于 2019 年 1 月 1 日...将继续挖掘。谢谢。 您的观点绝对正确 - 为了停止让结果超出我的范围,我将 NOT IN 移到 q0 上的 JOIN 内,这似乎解决了问题。试图完全理解为什么。上面贴出最终代码。

以上是关于SQL NOT EXISTS 子查询未按预期运行的主要内容,如果未能解决你的问题,请参考以下文章

sql [sql技巧]一些sql技巧#sql

sql 2008 r2 在sql 2008上兼容么

什么是sql注入如何防止sql注入

sql SQL Server和Oracle SQL的SQL语法的一些示例

请推荐一本SQL教程

plsqldeveloper导入sql文件速度