如何在指示的点上将此DB2 SQL查询更改为Right Join。

时间:2018-09-04 22:19:50

标签: sql db2 db2-400

我正在使用v6r1m0开发老式AS / 400 DB2系统。我正在处理一个从Access 2007开始的查询,但后来移至DBeaver v5.1.5.201808130751。对于那些不熟悉的人,这是一个类似于SQL Explorer和SQL Squirrel的SQL客户端。

我创建了如下所示的SQL,它似乎运行良好。两个子选择在Access中作为客户端查询太慢,因此我将它们创建为服务器端视图,虽然效果更好,但仍有改进的空间。然后,我将所有内容转换并合并到DBeaver中的单个DB2服务器端查询中,现在,它的运行速度很快。

但是,在SQL中有一点我认为我需要Right Join,因为我需要在左表中查看不匹配的行(实际上是子查询)。如果我在Access中执行此操作,则会收到错误3258 ...

  

“该SQL语句包含歧义,因此无法执行   外连接。要强制首先执行其中一个联接,请创建一个   执行第一个联接,然后包含该联接的单独查询   在您的SQL语句中查询。”

...如果我在DBeaver中进行操作,它的工作就像什么都没有改变,就像它仍然是Inner Join。没有错误消息,并且返回了相同数量的记录,尽管我确定肯定还有23条记录。

我从访问错误中了解到,我需要为带有Right Join的零件创建一个子查询,但是查询的复杂性使得我不确定如何执行。

如何按照访问错误的指示创建子查询。.

SQL在下面。需要Right Join的点带有注释,距查询末尾约10行。我需要查看BEERXT的所有记录,以及子查询RATES的所有匹配记录。我期望RATES中不匹配的字段将返回null。

注意:此数据库是一个古老的订单和库存系统,其中包含以非规范化和透视格式存储的各种数据。 Union子查询用于取消透视表。

SELECT 

LOADS.EMPID                 AS EMPID, 
LOADS.LDROLE                AS EMPROLE,
EMPLS.LHNAME                AS EMPNAME, 
DAILY.DAIDAT                AS INVDATE, 
DAILY.DAINV#                AS INVNUM, 
DAILY.DADAY#                AS INVDY, 
DAILY.DALOAD                AS LOAD, 
DAILY.DALIN#                AS INVLN, 
DAILY.DAITEM                AS ITEM, 
DAILY.DAUM                  AS UOM, 
DAILY.DAPCLS                AS CLASS, 
BEER.BXADDS                 AS BXDESC, 
BEER.BXDESC                 AS BXPKG, 
BEER.BXCCAT                 AS BXCAT, 
RATES.TYPECD                AS LDTYPE, 
RATES.RATECD                AS CMRCD, 
RATES.CMDESC                AS CMRDSC, 
RATES.CMRATE                AS CMRATE,
DAILY.DAQTY                 AS QTY, 
DAILY.DAQTY*RATES.CMRATE    AS SUBTOT

FROM VIPDTAB.LDHDR AS EMPLS 
    INNER JOIN (--THE FOLLOWING SUBSELECT IS TO UNPIVOT LDHIST
    (         SELECT LIYMD AS LDDATE, LILOAD AS LDNUM, LITRCK AS LDTRCK, 1 AS LDROLE, LIDRIV AS EMPID, COALESCE(LIRAT1,'0') AS BRATE, COALESCE(LICRT1,'0') AS CRATE FROM VIPDTAB.LDHIST WHERE CAST(LIDRIV AS INTEGER)>0 
        UNION SELECT LIYMD AS LDDATE, LILOAD AS LDNUM, LITRCK AS LDTRCK, 2 AS LDROLE, LIDRIV AS EMPID, COALESCE(LIRAT2,'0') AS BRATE, COALESCE(LICRT2,'0') AS CRATE FROM VIPDTAB.LDHIST WHERE CAST(LIHLP1 AS INTEGER)>0 
        UNION SELECT LIYMD AS LDDATE, LILOAD AS LDNUM, LITRCK AS LDTRCK, 3 AS LDROLE, LIDRIV AS EMPID, COALESCE(LIRAT3,'0') AS BRATE, COALESCE(LICRT3,'0') AS CRATE FROM VIPDTAB.LDHIST WHERE CAST(LIHLP2 AS INTEGER)>0
    ) AS LOADS
        INNER JOIN (--THE FOLLOWING SUBSELECT IS TO UNPIVOT LDHRAT
            (         SELECT LRCATG AS CATG, LRLDTY AS TYPECD, LRCRAT AS RATECD, 0 AS UNCODE,        0 AS LOWLIM,      0 AS UPRLIM,      0 AS CMRATE, LRCOLH AS CMDESC FROM VIPDTAB.LDHRAT 
                UNION SELECT LRCATG AS CATG, LRLDTY AS TYPECD, LRCRAT AS RATECD, 1 AS UNCODE,        1 AS LOWLIM, LRQTY1 AS UPRLIM, LRRAT1 AS CMRATE, LRCOLH AS CMDESC FROM VIPDTAB.LDHRAT
                UNION SELECT LRCATG AS CATG, LRLDTY AS TYPECD, LRCRAT AS RATECD, 2 AS UNCODE, LRQTY1+1 AS LOWLIM, LRQTY2 AS UPRLIM, LRRAT2 AS CMRATE, LRCOLH AS CMDESC FROM VIPDTAB.LDHRAT
                UNION SELECT LRCATG AS CATG, LRLDTY AS TYPECD, LRCRAT AS RATECD, 3 AS UNCODE, LRQTY2+1 AS LOWLIM, LRQTY3 AS UPRLIM, LRRAT3 AS CMRATE, LRCOLH AS CMDESC FROM VIPDTAB.LDHRAT
                UNION SELECT LRCATG AS CATG, LRLDTY AS TYPECD, LRCRAT AS RATECD, 4 AS UNCODE, LRQTY3+1 AS LOWLIM, LRQTY4 AS UPRLIM, LRRAT4 AS CMRATE, LRCOLH AS CMDESC FROM VIPDTAB.LDHRAT
                UNION SELECT LRCATG AS CATG, LRLDTY AS TYPECD, LRCRAT AS RATECD, 5 AS UNCODE, LRQTY4+1 AS LOWLIM, LRQTY5 AS UPRLIM, LRRAT5 AS CMRATE, LRCOLH AS CMDESC FROM VIPDTAB.LDHRAT
                UNION SELECT LRCATG AS CATG, LRLDTY AS TYPECD, LRCRAT AS RATECD, 6 AS UNCODE, LRQTY5+1 AS LOWLIM, LRQTY6 AS UPRLIM, LRRAT6 AS CMRATE, LRCOLH AS CMDESC FROM VIPDTAB.LDHRAT
                UNION SELECT LRCATG AS CATG, LRLDTY AS TYPECD, LRCRAT AS RATECD, 7 AS UNCODE, LRQTY6+1 AS LOWLIM, LRQTY7 AS UPRLIM, LRRAT7 AS CMRATE, LRCOLH AS CMDESC FROM VIPDTAB.LDHRAT
            ) AS RATES  
            INNER JOIN (VIPDTAB.BEERXT AS BEER --THIS NEEDS TO BE A RIGHT JOIN (I THINK?)
                INNER JOIN VIPDTAB.DAILYT AS DAILY 
                ON BEER.BXITEM = DAILY.DAITEM 
            ) ON RATES.CATG = BEER.BXCCAT
        ) ON (LOADS.LDDATE = DAILY.DAIDAT) AND (LOADS.LDNUM = DAILY.DALOAD) AND (LOADS.CRATE = RATES.RATECD)
    ) ON EMPLS.LHDRIV = LOADS.EMPID

WHERE DAILY.DAIDAT=20180716 AND LOADS.EMPID=36137 AND (DAILY.DAQTY BETWEEN LOWLIM AND UPRLIM)

ORDER BY LOADS.EMPID, DAILY.DAIDAT, DAILY.DAINV#, DAILY.DALIN#, BEER.BXCCAT, RATES.TYPECD, RATES.RATECD;

1 个答案:

答案 0 :(得分:0)

这是一个有点复杂的查询,因为您有很多嵌套的联接。没有示例数据和所需的输出,我无法真正给您一个真正的答案,但我可以为您进行故障排除。这是我在联接中看到的(包括所需的右外部联接):

要执行的第一次联接是BEER和DAILY之间在BEER.BXITEM = DAILY.DAITEM上的内部联接。这将过滤掉不在DAILY表中的任何BEER记录。

第二个联接:然后使用RATES.CATG = BEER.BXCCAT上的RIGHT OUTER JOIN将第一个联接的结果联接到RATES。在RATES中没有匹配项的其余BEER记录仍将存在,但结果集的RATES字段将为空。

第三次联接:然后使用(LOADS.LDDATE = DAILY.DAIDAT)和(LOADS.LDNUM = DAILY.DALOAD)和(LOADS.CRATE = RATES.RATECD)上的INNER JOIN将第二次联接的结果联接到LOADS )。最后一项将过滤掉RATECD中为空的所有RATES记录。如果您想包含缺少RATES值的结果集中的行,那么这也需要是RIGHT OUTER JOIN,但现在它还将包括RATES的所有行,而LOADS中没有匹配的CRATE的行,或其他任一加入条件均失败。

第四连接:最终,使用EMPLS.LHDRIV = LOADS.EMPID上的INNER JOIN将此连接的结果连接到EMPLS。这将再次过滤掉结果集中LOADS.EMPID为null的任何行,这将是缺少RATES记录的任何行(假设您将第三个联接转换为RIGHT OUTER JOIN)。再一次,您将需要另一个RIGHT OUTER JOIN来获取这些记录,但是再一次,您也可以选择您不想要的其他记录。

考虑到您不想提供示例数据和输出,我的最佳建议是从最里面的联接开始,并使用适当的联接类型和WHERE子句解决问题,直到获得所需的结果。