联接日期在一定范围内的Informix SQL查询

时间:2019-06-05 02:46:06

标签: sql informix

我汇总了一个查询,该查询从几张表中获取了很多数据,但我需要输入一个人工价格,其中劳工表中的effective_datemax(labourates.effective_date),即小于或等于labourline.alloc_entry_date

联接位于labourline.alloc_entry_datelabourline.part_code(两者都在labourates表中)

我尝试了很多外部联接选项,但是我对当前的联接方法并不十分了解(从*=开始就是这样)

当前查询是这样:

Select  'Labour' part_type,
    labourline.order_num,
    ordhead.order_date,
    labourhead.alloc_entry_date,
    labourline.part_code,
    product.desc_text,
    ordhead.cust_code,
    product.cat_code,
    product.prodgrp_code,
    product.maingrp_code,
    product.ware_code,
    0 unit_rate_amt,
    labourline.order_qty,
    labourline.uom_code,
    product.weight_qty,
    product.cubic_qty,
    product.area_qty,
    product.length_qty
from    ordhead,
    labourline,
    labourhead,
    product
where   labourline.cmpy_code = 'EC'
and product.cmpy_code = 'EC'
and ordhead.cmpy_code = 'EC'
and labourhead.cmpy_code = 'EC'
and labourline.part_code = product.part_code
and labourline.order_num = ordhead.order_num
and labourline.order_num = labourhead.order_num
and ordhead.order_date >= MDY(08,01,2018)
and ordhead.order_date < MDY(08,01,2019)

当给定unit_rate_amtPartCode时,这段代码为我提供了我需要的CheckDate

Select   unit_rate_amt
from    labourates
where   part_code = 'PartCode'
and effective_date = (
        select max(effective_date) from labourates
        where part_code = 'PartCode'
        and effective_date <= 'CheckDate'
    )

将其合并到初始查询中以替换0 unit_rate_amt,证明是我无法解决的问题。

2 个答案:

答案 0 :(得分:1)

我倾向于使用我所谓的TDQD —测试驱动查询设计。我逐步建立了一个复杂的查询。您为我提供了一个巨大的飞跃,它从您的主查询和需要集成到主查询中的子查询开始。开发独立子查询正是TDQD鼓励的事情。

在询问关于SO的问题时,请确保将诸如查询之类的字段的数量最小化。例如,product.weight_qtyproduct.cubic_qtyproduct.area_qtyproduct.length_qty这四个项目在您的“现实生活”查询中无疑都是很重要的,但它们确实不会影响我们所以。其中之一是很多。也许甚至因为您已从desc_text中选择了product而变得矫kill过正。

提供表的概要架构也很重要-我的TDQD不受测试驱动,因为您没有提供可用的最小表架构,更不用说要处理的样本数据和预期的输出了。如果您的问题更容易回答,因为您已经提供了该信息,那么您将获得更好的答案。

作为一般的经验法则,在当前的千年中,您不应再在SQL中使用FROM table1, table2, table3, …表示法。您应该显式使用JOIN。

步骤1-简化主查询并使用JOIN

以您的主要查询为例,我对其进行了改进:

SELECT 'Labour' AS part_type,
       ll.order_num,
       oh.order_date,
       lh.alloc_entry_date,
       ll.part_code,
       pr.desc_text,
       oh.cust_code,
       0 unit_rate_amt,
       ll.order_qty,
       ll.uom_code,
       pr.length_qty
  FROM ordhead    AS oh
  JOIN labourline AS ll ON oh.order_num = ll.order_num AND oh.cmpy_code = ll.cmpy_code
  JOIN labourhead AS lh ON lh.order_num = ll.order_num AND lh.cmpy_code = ll.cmpy_code
  JOIN product    AS pr ON pr.part_code = ll.part_code AND pr.cmpy_code = pr.cmpy_code
 WHERE ll.cmpy_code = 'EC'
   AND pr.cmpy_code = 'EC'
   AND oh.cmpy_code = 'EC'
   AND lh.cmpy_code = 'EC'
   AND oh.order_date >= MDY(08,01,2018)
   AND oh.order_date < MDY(08,01,2019)

我使用AS来介绍表的缩写。我经常使用单字母缩写。在这里,双字母似乎更合适。我从选择列表部分中删除了一些元素,因为它们对您的问题不够重要。

从您反复使用xyz.cmpy_code = 'EC'推断出,可以将表与cmpy_code进行连接作为连接条件的一部分;我在ON条件中使用该连接。我还推断出labourline是此查询的中心表,并首先列出了它。其他表连接到它,而不是彼此连接。我在查询中保留了诸如AND pr.cmpy_code = 'EC'之类的重复条件,但是除非查询计划显示出通过保持常数项带来的显着收益,否则我可能会消除除ll.cmpy_code = 'EC'之外的所有条件。

步骤2 —集成子查询

这需要对“工作子查询”进行一些解释。我假设您所指的CheckDatelabourline.alloc_entry_date,零件代码是labourline.part_code。使用JOIN表示法,可以很容易地将子查询滑动到主查询中,如下所示:

SELECT 'Labour' AS part_type,
       ll.order_num,
       oh.order_date,
       lh.alloc_entry_date,
       ll.part_code,
       pr.desc_text,
       oh.cust_code,
       lr.unit_rate_amt,
       ll.order_qty,
       ll.uom_code,
       pr.length_qty
  FROM labourline AS ll
  JOIN ordhead    AS oh ON oh.order_num = ll.order_num AND oh.cmpy_code = ll.cmpy_code
  JOIN labourhead AS lh ON lh.order_num = ll.order_num AND lh.cmpy_code = ll.cmpy_code
  JOIN product    AS pr ON pr.part_code = ll.part_code AND pr.cmpy_code = ll.cmpy_code
  JOIN (SELECT lr1.part_code, lr1.unit_rate_amt AS unit_rate_amt
          FROM labourates AS lr1
         WHERE lr1.part_code = ll.part_code
           AND lr1.effective_date =
               (SELECT MAX(effective_date)
                  FROM labourates AS lr2
                 WHERE lr2.part_code =  ll.part_code
                   AND lr2.effective_date <= ll.alloca_entry_date
               )
       )          AS lr ON lr.part_code = ll.part_code
 WHERE ll.cmpy_code = 'EC'
   AND oh.order_date >= MDY(08,01,2018)
   AND oh.order_date < MDY(08,01,2019)

这是一个相关的子查询,因为在子查询中引用了ll.part_codell.alloc_entry_date。我怀疑是否存在将相关子查询转换为不相关子查询的方法。当然,如果/如果这会导致响应时间慢的问题,那是我寻求改进的第一位。 ll.alloc_entry_date值对于子查询至关重要,因此关联可能是不可避免的。如果相关性不可避免,那么确保适当的索引就变得至关重要。甚至在cmpy_code和其他列上具有联接的主查询,也会从适当的索引中受益。

答案 1 :(得分:0)

为了完整起见,我设法解决了这个问题。它会在某处创建重复对象,我不知道该在哪里但区别在于它的作用:

Select  distinct 'Labour' part_type,
    ll.order_num,
    oh.order_date,
    lh.alloc_entry_date,
    ll.part_code,
    pr.desc_text,
    oh.cust_code,
    oh.sale_code,
    pr.cat_code,
    pr.prodgrp_code,
    pr.maingrp_code,
    pr.ware_code,
    lr1.unit_rate_amt,
    ll.order_qty,
    ll.uom_code,
    pr.weight_qty,
    pr.cubic_qty,
    pr.area_qty,
    pr.length_qty
from    labourline AS ll
JOIN    ordhead    AS oh ON oh.order_num = ll.order_num AND oh.cmpy_code = ll.cmpy_code
JOIN    labourhead AS lh ON lh.order_num = ll.order_num AND lh.cmpy_code = ll.cmpy_code
JOIN    product    AS pr ON pr.part_code = ll.part_code AND pr.cmpy_code = ll.cmpy_code
JOIN    labourates    AS lr1 ON lr1.part_code = ll.part_code AND lr1.cmpy_code = ll.cmpy_code
where   ll.cmpy_code = 'EC'
and oh.order_date >= MDY(08,01,2017)
and oh.order_date < MDY(08,01,2018)
and lr1.effective_date = 
    (
    SELECT  MAX(effective_date)
    FROM    labourates lr2
    WHERE   lr2.part_code =  ll.part_code
    AND lr2.effective_date <= lh.alloc_entry_date
    AND lr2.ware_code = ll.ware_code
    )

感谢@Jonathan Leffler教给我了join结构。