如何在Informix风格的SQL中使用`outer`?

时间:2013-06-20 13:39:01

标签: sql informix

我继承了一些<cough>丑陋的</cough>代码,其中包含一个非常笨拙的SQL语句,它会访问Informix数据库。这段代码计算了SQL的各个部分,并进行了大量的字符串连接,但我让它吐出了实际发送给Informix的内容并尝试在我的SQL查询工具中使用它。它在服务器上运行时是有用的,但是当我尝试在FlySpeed SQL(这是一个在办公室使用的“已批准”工具)中运行它时,它会抱怨outer为未知关键字。谷歌搜索让我无处可去,所以我猜这是LEFT OUTER JOIN的Informix快捷方式,但是用它代替它没有解决问题,所以我猜它只是FlySpeed中的一个错误。

SQL完全没有格式化,我猜测它是FlySpeed绊倒的一部分。

SELECT A.CRSPD_SETID, A.CRSPD_CUST_ID, F.ST_ID_NUM as STMT_NBR, F.ST_DT, A.BUSINESS_UNIT, H.ASOF_DT, H.DUE_DT, A.ITEM, H.CONTRACT_NUM, D.DESCR as ENTRY_TYPE_DESCR, G.DESCR as ENTRY_REASON_DESCR, SUM(A.BAL_AMT) as ORIG_BAL_AMT, SUM(H.BAL_AMT), C.NAME1, B.ADDRESS1, B.ADDRESS2, B.ADDRESS3, B.ADDRESS4, B.CITY, B.STATE, B.POSTAL, A.BAL_CURRENCY, A.CUST_ID, A.ENTRY_TYPE as ORIG_ENTRY_TYPE, CASE WHEN A.ENTRY_TYPE = 'PY' OR A.ENTRY_TYPE = 'BGB' THEN 'AA' || substr(A.ENTRY_TYPE,1,3) ELSE  substr(A.ENTRY_TYPE,1,3) END, A.ENTRY_REASON as ORIG_ENTRY_REASON, C.CUSTOMER_TYPE, K.AR_LVL, H.ORDER_NO FROM PS_STMT_CUST_DTL A, PS_CUST_ADDRESS B, PS_CUSTOMER C, PS_SET_CNTRL_REC E, PS_STMT_CUST F, PS_ENTRY_TYPE_TBL D, PS_ENTRY_REASN_TBL G, outer PS_ITEM H, outer PS_BI_TYPE K WHERE A.ADDRESS_SEQ_NUM = B.ADDRESS_SEQ_NUM AND B.EFFDT = (SELECT MAX(B_ED.EFFDT) FROM PS_CUST_ADDRESS B_ED Where B.SETID = B_ED.SETID AND B.CUST_ID = B_ED.CUST_ID AND B.ADDRESS_SEQ_NUM = B_ED.ADDRESS_SEQ_NUM AND B_ED.EFFDT <=  '06/19/2013') AND A.CRSPD_SETID = B.SETID AND A.CRSPD_CUST_ID = B.CUST_ID AND B.SETID = C.SETID AND B.CUST_ID = C.CUST_ID AND B.ADDRESS_SEQ_NUM = C.ADDRESS_SEQ_NUM AND G.ENTRY_TYPE = A.ENTRY_TYPE AND G.ENTRY_REASON = A.ENTRY_REASON AND G.SETID = E.SETID AND G.SETID = D.SETID AND G.ENTRY_TYPE = D.ENTRY_TYPE AND E.SETCNTRLVALUE = A.BUSINESS_UNIT AND E.RECNAME = 'ENTRY_TYPE_TBL' AND A.CRSPD_SETID = F.CRSPD_SETID AND A.CRSPD_CUST_ID = F.CRSPD_CUST_ID AND A.ST_ID_NUM = F.ST_ID_NUM AND A.BUSINESS_UNIT = H.BUSINESS_UNIT AND A.CUST_ID = H.CUST_ID AND A.ITEM = H.ITEM AND A.ITEM_LINE = H.ITEM_LINE AND substr(A.ENTRY_TYPE,1,3) = K.BILL_TYPE_ID AND K.SETID = 'SPN' AND K.EFFDT = (SELECT MAX(C_ED.EFFDT) FROM PS_BI_TYPE C_ED WHERE K.SETID = C_ED.SETID AND K.BILL_TYPE_ID = C_ED.BILL_TYPE_ID AND C_ED.EFFDT <=  '06/19/2013') AND K.EFF_STATUS = 'A' AND A.CRSPD_CUST_ID =  '000331' AND A.CRSPD_SETID = 'SPN' AND F.ST_DT = '' AND F.ST_ID_NUM = '' GROUP BY A.CRSPD_SETID, A.CRSPD_CUST_ID, F.ST_ID_NUM, F.ST_DT, A.BUSINESS_UNIT ,H.ASOF_DT, H.DUE_DT, A.ITEM, H.CONTRACT_NUM, D.DESCR, G.DESCR, C.NAME1 ,B.ADDRESS1, B.ADDRESS2, B.ADDRESS3, B.ADDRESS4, B.CITY, B.STATE ,B.POSTAL, A.BAL_CURRENCY, A.CUST_ID, A.ENTRY_TYPE ,25, A.ENTRY_REASON, C.CUSTOMER_TYPE, K.AR_LVL, H.ORDER_NO UNION ALL  SELECT A.CRSPD_SETID, A.CRSPD_CUST_ID, F.ST_ID_NUM as STMT_NBR, F.ST_DT, A.BUSINESS_UNIT, H.ASOF_DT, H.DUE_DT, A.ITEM, H.CONTRACT_NUM, D.DESCR as ENTRY_TYPE_DESCR, G.DESCR as ENTRY_REASON_DESCR, SUM(A.BAL_AMT) as ORIG_BAL_AMT, SUM(H.BAL_AMT), C.NAME1, B.ADDRESS1, B.ADDRESS2, B.ADDRESS3, B.ADDRESS4, B.CITY, B.STATE, B.POSTAL, A.BAL_CURRENCY, A.CUST_ID, A.ENTRY_TYPE as ORIG_ENTRY_TYPE, CASE WHEN A.ENTRY_TYPE = 'PY' OR A.ENTRY_TYPE = 'BGB' THEN 'AA' || substr(A.ENTRY_TYPE,1,3) ELSE  substr(A.ENTRY_TYPE,1,3) END, A.ENTRY_REASON as ORIG_ENTRY_REASON, C.CUSTOMER_TYPE, K.AR_LVL, H.ORDER_NO FROM PS_AR_STMT_CUSDT_H A, PS_CUST_ADDRESS B, PS_CUSTOMER C, PS_SET_CNTRL_REC E, PS_AR_STMT_CUST_H F, PS_ENTRY_TYPE_TBL D, PS_ENTRY_REASN_TBL G, outer PS_AR_ITEM_H H, outer PS_BI_TYPE K WHERE A.ADDRESS_SEQ_NUM = B.ADDRESS_SEQ_NUM AND B.EFFDT = (SELECT MAX(B_ED.EFFDT) FROM PS_CUST_ADDRESS B_ED Where B.SETID = B_ED.SETID AND B.CUST_ID = B_ED.CUST_ID AND B.ADDRESS_SEQ_NUM = B_ED.ADDRESS_SEQ_NUM AND B_ED.EFFDT <=  '06/19/2013') AND A.CRSPD_SETID = B.SETID AND A.CRSPD_CUST_ID = B.CUST_ID AND B.SETID = C.SETID AND B.CUST_ID = C.CUST_ID AND B.ADDRESS_SEQ_NUM = C.ADDRESS_SEQ_NUM AND G.ENTRY_TYPE = A.ENTRY_TYPE AND G.ENTRY_REASON = A.ENTRY_REASON AND G.SETID = E.SETID AND G.SETID = D.SETID AND G.ENTRY_TYPE = D.ENTRY_TYPE AND E.SETCNTRLVALUE = A.BUSINESS_UNIT AND E.RECNAME = 'ENTRY_TYPE_TBL' AND A.CRSPD_SETID = F.CRSPD_SETID AND A.CRSPD_CUST_ID = F.CRSPD_CUST_ID AND A.ST_ID_NUM = F.ST_ID_NUM AND A.BUSINESS_UNIT = H.BUSINESS_UNIT AND A.CUST_ID = H.CUST_ID AND A.ITEM = H.ITEM AND A.ITEM_LINE = H.ITEM_LINE AND substr(A.ENTRY_TYPE,1,3) = K.BILL_TYPE_ID AND K.SETID = 'SPN' AND K.EFFDT = (SELECT MAX(C_ED.EFFDT) FROM PS_BI_TYPE C_ED WHERE K.SETID = C_ED.SETID AND K.BILL_TYPE_ID = C_ED.BILL_TYPE_ID AND C_ED.EFFDT <=  '06/19/2013') AND K.EFF_STATUS = 'A' AND A.CRSPD_CUST_ID =  '000331' AND A.CRSPD_SETID = 'SPN' AND F.ST_DT = '' AND F.ST_ID_NUM = '' GROUP BY A.CRSPD_SETID, A.CRSPD_CUST_ID, F.ST_ID_NUM, F.ST_DT, A.BUSINESS_UNIT ,H.ASOF_DT, H.DUE_DT, A.ITEM, H.CONTRACT_NUM, D.DESCR, G.DESCR, C.NAME1 ,B.ADDRESS1, B.ADDRESS2, B.ADDRESS3, B.ADDRESS4, B.CITY, B.STATE ,B.POSTAL, A.BAL_CURRENCY, A.CUST_ID, A.ENTRY_TYPE ,25, A.ENTRY_REASON, C.CUSTOMER_TYPE, K.AR_LVL, H.ORDER_NO ORDER BY 2,3,4,25,8,11,24

我是否认为OUTER只是LEFT OUTER JOIN的简写(可能是Informix风格的简写)?

更新 :我发现Informix here实际上使用了OUTER,但是我尚未找到任何关于如何的解释。显然,搜索结果绝大多数都支持包含正常语法的内容。即使this very useful RDBMS comparison几乎没有关于Informix的内容。

这是格式化的SQL(抱歉大小!):

SELECT A.CRSPD_SETID,
       A.CRSPD_CUST_ID,
       F.ST_ID_NUM AS STMT_NBR,
       F.ST_DT,
       A.BUSINESS_UNIT,
       H.ASOF_DT,
       H.DUE_DT,
       A.ITEM,
       H.CONTRACT_NUM,
       D.DESCR AS ENTRY_TYPE_DESCR,
       G.DESCR AS ENTRY_REASON_DESCR,
       SUM(A.BAL_AMT) AS ORIG_BAL_AMT,
       SUM(H.BAL_AMT),
       C.NAME1,
       B.ADDRESS1,
       B.ADDRESS2,
       B.ADDRESS3,
       B.ADDRESS4,
       B.CITY,
       B.STATE,
       B.POSTAL,
       A.BAL_CURRENCY,
       A.CUST_ID,
       A.ENTRY_TYPE AS ORIG_ENTRY_TYPE,
       CASE
           WHEN A.ENTRY_TYPE = 'PY'
                OR A.ENTRY_TYPE = 'BGB' THEN 'AA' || substr(A.ENTRY_TYPE,1,3)
           ELSE substr(A.ENTRY_TYPE,1,3)
       END,
       A.ENTRY_REASON AS ORIG_ENTRY_REASON,
       C.CUSTOMER_TYPE,
       K.AR_LVL,
       H.ORDER_NO
FROM PS_STMT_CUST_DTL A,
     PS_CUST_ADDRESS B,
     PS_CUSTOMER C,
     PS_SET_CNTRL_REC E,
     PS_STMT_CUST F,
     PS_ENTRY_TYPE_TBL D,
     PS_ENTRY_REASN_TBL G,
     OUTER PS_ITEM H,
           OUTER PS_BI_TYPE K
WHERE A.ADDRESS_SEQ_NUM = B.ADDRESS_SEQ_NUM
  AND B.EFFDT =
    (SELECT MAX(B_ED.EFFDT)
     FROM PS_CUST_ADDRESS B_ED
     WHERE B.SETID = B_ED.SETID
       AND B.CUST_ID = B_ED.CUST_ID
       AND B.ADDRESS_SEQ_NUM = B_ED.ADDRESS_SEQ_NUM
       AND B_ED.EFFDT <= '06/19/2013')
  AND A.CRSPD_SETID = B.SETID
  AND A.CRSPD_CUST_ID = B.CUST_ID
  AND B.SETID = C.SETID
  AND B.CUST_ID = C.CUST_ID
  AND B.ADDRESS_SEQ_NUM = C.ADDRESS_SEQ_NUM
  AND G.ENTRY_TYPE = A.ENTRY_TYPE
  AND G.ENTRY_REASON = A.ENTRY_REASON
  AND G.SETID = E.SETID
  AND G.SETID = D.SETID
  AND G.ENTRY_TYPE = D.ENTRY_TYPE
  AND E.SETCNTRLVALUE = A.BUSINESS_UNIT
  AND E.RECNAME = 'ENTRY_TYPE_TBL'
  AND A.CRSPD_SETID = F.CRSPD_SETID
  AND A.CRSPD_CUST_ID = F.CRSPD_CUST_ID
  AND A.ST_ID_NUM = F.ST_ID_NUM
  AND A.BUSINESS_UNIT = H.BUSINESS_UNIT
  AND A.CUST_ID = H.CUST_ID
  AND A.ITEM = H.ITEM
  AND A.ITEM_LINE = H.ITEM_LINE
  AND substr(A.ENTRY_TYPE,1,3) = K.BILL_TYPE_ID
  AND K.SETID = 'SPN'
  AND K.EFFDT =
    (SELECT MAX(C_ED.EFFDT)
     FROM PS_BI_TYPE C_ED
     WHERE K.SETID = C_ED.SETID
       AND K.BILL_TYPE_ID = C_ED.BILL_TYPE_ID
       AND C_ED.EFFDT <= '06/19/2013')
  AND K.EFF_STATUS = 'A'
  AND A.CRSPD_CUST_ID = '000331'
  AND A.CRSPD_SETID = 'SPN'
  AND F.ST_DT = ''
  AND F.ST_ID_NUM = ''
GROUP BY A.CRSPD_SETID,
         A.CRSPD_CUST_ID,
         F.ST_ID_NUM,
         F.ST_DT,
         A.BUSINESS_UNIT ,
         H.ASOF_DT,
         H.DUE_DT,
         A.ITEM,
         H.CONTRACT_NUM,
         D.DESCR,
         G.DESCR,
         C.NAME1 ,
         B.ADDRESS1,
         B.ADDRESS2,
         B.ADDRESS3,
         B.ADDRESS4,
         B.CITY,
         B.STATE ,
         B.POSTAL,
         A.BAL_CURRENCY,
         A.CUST_ID,
         A.ENTRY_TYPE ,
         25,
         A.ENTRY_REASON,
         C.CUSTOMER_TYPE,
         K.AR_LVL,
         H.ORDER_NO
UNION ALL
SELECT A.CRSPD_SETID,
       A.CRSPD_CUST_ID,
       F.ST_ID_NUM AS STMT_NBR,
       F.ST_DT,
       A.BUSINESS_UNIT,
       H.ASOF_DT,
       H.DUE_DT,
       A.ITEM,
       H.CONTRACT_NUM,
       D.DESCR AS ENTRY_TYPE_DESCR,
       G.DESCR AS ENTRY_REASON_DESCR,
       SUM(A.BAL_AMT) AS ORIG_BAL_AMT,
       SUM(H.BAL_AMT),
       C.NAME1,
       B.ADDRESS1,
       B.ADDRESS2,
       B.ADDRESS3,
       B.ADDRESS4,
       B.CITY,
       B.STATE,
       B.POSTAL,
       A.BAL_CURRENCY,
       A.CUST_ID,
       A.ENTRY_TYPE AS ORIG_ENTRY_TYPE,
       CASE
           WHEN A.ENTRY_TYPE = 'PY'
                OR A.ENTRY_TYPE = 'BGB' THEN 'AA' || substr(A.ENTRY_TYPE,1,3)
           ELSE substr(A.ENTRY_TYPE,1,3)
       END,
       A.ENTRY_REASON AS ORIG_ENTRY_REASON,
       C.CUSTOMER_TYPE,
       K.AR_LVL,
       H.ORDER_NO
FROM PS_AR_STMT_CUSDT_H A,
     PS_CUST_ADDRESS B,
     PS_CUSTOMER C,
     PS_SET_CNTRL_REC E,
     PS_AR_STMT_CUST_H F,
     PS_ENTRY_TYPE_TBL D,
     PS_ENTRY_REASN_TBL G,
     OUTER PS_AR_ITEM_H H,
           OUTER PS_BI_TYPE K
WHERE A.ADDRESS_SEQ_NUM = B.ADDRESS_SEQ_NUM
  AND B.EFFDT =
    (SELECT MAX(B_ED.EFFDT)
     FROM PS_CUST_ADDRESS B_ED
     WHERE B.SETID = B_ED.SETID
       AND B.CUST_ID = B_ED.CUST_ID
       AND B.ADDRESS_SEQ_NUM = B_ED.ADDRESS_SEQ_NUM
       AND B_ED.EFFDT <= '06/19/2013')
  AND A.CRSPD_SETID = B.SETID
  AND A.CRSPD_CUST_ID = B.CUST_ID
  AND B.SETID = C.SETID
  AND B.CUST_ID = C.CUST_ID
  AND B.ADDRESS_SEQ_NUM = C.ADDRESS_SEQ_NUM
  AND G.ENTRY_TYPE = A.ENTRY_TYPE
  AND G.ENTRY_REASON = A.ENTRY_REASON
  AND G.SETID = E.SETID
  AND G.SETID = D.SETID
  AND G.ENTRY_TYPE = D.ENTRY_TYPE
  AND E.SETCNTRLVALUE = A.BUSINESS_UNIT
  AND E.RECNAME = 'ENTRY_TYPE_TBL'
  AND A.CRSPD_SETID = F.CRSPD_SETID
  AND A.CRSPD_CUST_ID = F.CRSPD_CUST_ID
  AND A.ST_ID_NUM = F.ST_ID_NUM
  AND A.BUSINESS_UNIT = H.BUSINESS_UNIT
  AND A.CUST_ID = H.CUST_ID
  AND A.ITEM = H.ITEM
  AND A.ITEM_LINE = H.ITEM_LINE
  AND substr(A.ENTRY_TYPE,1,3) = K.BILL_TYPE_ID
  AND K.SETID = 'SPN'
  AND K.EFFDT =
    (SELECT MAX(C_ED.EFFDT)
     FROM PS_BI_TYPE C_ED
     WHERE K.SETID = C_ED.SETID
       AND K.BILL_TYPE_ID = C_ED.BILL_TYPE_ID
       AND C_ED.EFFDT <= '06/19/2013')
  AND K.EFF_STATUS = 'A'
  AND A.CRSPD_CUST_ID = '000331'
  AND A.CRSPD_SETID = 'SPN'
  AND F.ST_DT = ''
  AND F.ST_ID_NUM = ''
GROUP BY A.CRSPD_SETID,
         A.CRSPD_CUST_ID,
         F.ST_ID_NUM,
         F.ST_DT,
         A.BUSINESS_UNIT ,
         H.ASOF_DT,
         H.DUE_DT,
         A.ITEM,
         H.CONTRACT_NUM,
         D.DESCR,
         G.DESCR,
         C.NAME1 ,
         B.ADDRESS1,
         B.ADDRESS2,
         B.ADDRESS3,
         B.ADDRESS4,
         B.CITY,
         B.STATE ,
         B.POSTAL,
         A.BAL_CURRENCY,
         A.CUST_ID,
         A.ENTRY_TYPE ,
         25,
         A.ENTRY_REASON,
         C.CUSTOMER_TYPE,
         K.AR_LVL,
         H.ORDER_NO
ORDER BY 2,
         3,
         4,
         25,
         8,
         11,
         24

3 个答案:

答案 0 :(得分:1)

  

我是否认为OUTER只是速记(可能是Informix风格的   LEFT OUTER JOIN的速记?

是的,你完全正确。

Informix-4GL Reference Manual

引用
  

查询1 - 使用简单加入

SELECT customer.customer_num, lname, order_num
    FROM customer, orders
    WHERE customer.customer_num = orders.order_num
     

查询2 - 使用外部加入

SELECT customer.customer_num, lname, order_num
    FROM customer, OUTER orders
    WHERE customer.customer_num = orders.customer_num

在Informix中,当OUTER放在可以包含空值的表前面时,连接被指定为外部。

答案 1 :(得分:1)

有关Informix外部语法的信息: http://pic.dhe.ibm.com/infocenter/idshelp/v117/index.jsp?topic=%2Fcom.ibm.sqls.doc%2Fsqls.htm

IBM的时髦文档不允许直接链接,因此在那里搜索OUTER。

这适用于Informix 11.7,不确定您使用的是哪个版本。

基本上,外部表将是where子句中任何连接条件下的子服务表,并且实际上是左外连接。另请注意,使用Informix语法,from子句中指定表的顺序非常重要。

答案 2 :(得分:1)

Informix风格的OUTER连接不仅仅是LEFT OUTER JOIN的捷径,但它是一个适度的近似值。有很多细节,为什么它不那么简单。

Informix OUTER Joins的在线说明,其中一些比您示例中的查询复杂得多。

将UNION查询的前半部分翻译成更现代的表示法,您将得到:

SELECT A.CRSPD_SETID,
       A.CRSPD_CUST_ID,
       F.ST_ID_NUM AS STMT_NBR,
       F.ST_DT,
       A.BUSINESS_UNIT,
       H.ASOF_DT,
       H.DUE_DT,
       A.ITEM,
       H.CONTRACT_NUM,
       D.DESCR AS ENTRY_TYPE_DESCR,
       G.DESCR AS ENTRY_REASON_DESCR,
       SUM(A.BAL_AMT) AS ORIG_BAL_AMT,
       SUM(H.BAL_AMT),
       C.NAME1,
       B.ADDRESS1,
       B.ADDRESS2,
       B.ADDRESS3,
       B.ADDRESS4,
       B.CITY,
       B.STATE,
       B.POSTAL,
       A.BAL_CURRENCY,
       A.CUST_ID,
       A.ENTRY_TYPE AS ORIG_ENTRY_TYPE,
       CASE
           WHEN A.ENTRY_TYPE = 'PY'
                OR A.ENTRY_TYPE = 'BGB' THEN 'AA' || substr(A.ENTRY_TYPE,1,3)
           ELSE substr(A.ENTRY_TYPE,1,3)
       END,
       A.ENTRY_REASON AS ORIG_ENTRY_REASON,
       C.CUSTOMER_TYPE,
       K.AR_LVL,
       H.ORDER_NO
  FROM PS_STMT_CUST_DTL A
  JOIN PS_CUST_ADDRESS B
    ON A.ADDRESS_SEQ_NUM = B.ADDRESS_SEQ_NUM AND
       A.CRSPD_SETID = B.SETID AND
       A.CRSPD_CUST_ID = B.CUST_ID
  JOIN PS_CUSTOMER C
    ON B.SETID = C.SETID AND
       B.CUST_ID = C.CUST_ID AND
       B.ADDRESS_SEQ_NUM = C.ADDRESS_SEQ_NUM
  JOIN PS_SET_CNTRL_REC E
    ON E.SETCNTRLVALUE = A.BUSINESS_UNIT AND
       E.RECNAME = 'ENTRY_TYPE_TBL'
  JOIN PS_STMT_CUST F
    ON A.CRSPD_SETID = F.CRSPD_SETID AND
       A.CRSPD_CUST_ID = F.CRSPD_CUST_ID AND
       A.ST_ID_NUM = F.ST_ID_NUM
  JOIN PS_ENTRY_REASN_TBL G
    ON G.ENTRY_TYPE = A.ENTRY_TYPE AND
       G.ENTRY_REASON = A.ENTRY_REASON AND
       G.SETID = E.SETID AND
  JOIN PS_ENTRY_TYPE_TBL D
    ON G.SETID = D.SETID AND
       G.ENTRY_TYPE = D.ENTRY_TYPE
  LEFT OUTER JOIN PS_ITEM H
    ON A.BUSINESS_UNIT = H.BUSINESS_UNIT AND
       A.CUST_ID = H.CUST_ID AND
       A.ITEM = H.ITEM AND
       A.ITEM_LINE = H.ITEM_LINE
  LEFT OUTER JOIN PS_BI_TYPE K
    ON SUBSTR(A.ENTRY_TYPE,1,3) = K.BILL_TYPE_ID
 WHERE B.EFFDT =
       (SELECT MAX(B_ED.EFFDT)
          FROM PS_CUST_ADDRESS B_ED
         WHERE B.SETID = B_ED.SETID
           AND B.CUST_ID = B_ED.CUST_ID
           AND B.ADDRESS_SEQ_NUM = B_ED.ADDRESS_SEQ_NUM
           AND B_ED.EFFDT <= '06/19/2013')
   AND K.SETID = 'SPN'
   AND K.EFFDT =
       (SELECT MAX(C_ED.EFFDT)
          FROM PS_BI_TYPE C_ED
         WHERE K.SETID = C_ED.SETID
           AND K.BILL_TYPE_ID = C_ED.BILL_TYPE_ID
           AND C_ED.EFFDT <= '06/19/2013')
   AND K.EFF_STATUS = 'A'
   AND A.CRSPD_CUST_ID = '000331'
   AND A.CRSPD_SETID = 'SPN'
   AND F.ST_DT = ''
   AND F.ST_ID_NUM = ''
 GROUP BY A.CRSPD_SETID,
          A.CRSPD_CUST_ID,
          F.ST_ID_NUM,
          F.ST_DT,
          A.BUSINESS_UNIT ,
          H.ASOF_DT,
          H.DUE_DT,
          A.ITEM,
          H.CONTRACT_NUM,
          D.DESCR,
          G.DESCR,
          C.NAME1 ,
          B.ADDRESS1,
          B.ADDRESS2,
          B.ADDRESS3,
          B.ADDRESS4,
          B.CITY,
          B.STATE,
          B.POSTAL,
          A.BAL_CURRENCY,
          A.CUST_ID,
          A.ENTRY_TYPE,
          25,
          A.ENTRY_REASON,
          C.CUSTOMER_TYPE,
          K.AR_LVL,
          H.ORDER_NO

由于表格和多列连接条件的数量庞大,这相当复杂。但是,外连接结构是直接的 - 两个外连接都直接与主表PS_STMT_CUST_DTL相关,后者给出了别名A.

我很确定SQL可以简化。例如,在编写它时,Informix可能不支持“FROM子句中的子查询”。但是这两个SUM值可能会被放入子查询中,这将简化GROUP BY子句(从主查询中删除它)。