如何比较两个连接的值并基于总和值强制使用另一个值

时间:2017-07-11 05:08:59

标签: sql db2

感谢您提前获得任何反馈。

我对这个SQL脚本有以下难题。我正在从db2服务器读取,该脚本由三个表组成,但其中两个表给我一个问题。

我有表1,这个表是位置表。该表包含两个关键列PL_COUNTLOC_SYSIDPL_COUNT告诉许多每个位置适合多少个plts。

表2,此表是库存表,该表仅包含LOC_SYSID个字段,但LOC_SYSID列是查找该位置中有多少个plts的关键。为了找到位置中有多少个plts,我做了一个总和来确定每个位置使用LOC_SYSID加入多少个plts。这很完美,但是当库存表的总和返回的记录多于PL_COUNT可以容纳的记录时。总和不正确我想强制脚本使用位置表中的PL_COUNT值。

我尝试了几件事,但没有运气。方法是使用案例,当库存表的总和>比位置表中的PL_CCOUNT,我会强制使用PL_COUNT。但是,案例方法不起作用,我每次都会遇到错误。在这一点上,我没有想法,也不知道这种方法是否可行。

再次感谢任何反馈

            LOCATIONS TABLE 1
           |LOC_SYSID |PL_COUNT|whsesysid|
           |10001     |2       |1        |
           |10002     |2       |1        |
           |10003     |2       |1        |
           |10004     |2       |2        |
           |10005     |1       |2        |
           |10006     |1       |2        |


            INVENTORY TABLE 2
            PLT_SYSID |LOC_SYSID|whsesysid|
           |1         |10001    |1        |
           |2         |10001    |1        |
           |3         |10001    |1        |
           |4         |10002    |1        |
           |5         |10002    |1        |
           |6         |10002    |1        |
           |7         |10002    |1        |
           |8         |10003    |1        |                 
           |9         |10003    |1        |
           |10        |10003    |1        |
           |11        |10004    |2        |
           |12        |10005    |2        |
           |13        |10006    |2        |
           |14        |10006    |2        |
           |15        |10006    |2        |
           |16        |10006    |2        |                 



            SQL OUTPUT 
            whseSysId |whsename|availableFootprints |usedFootprints
           |1         |10001   |8                   |10              In this result it should be 8, but since ls1 has 3, ls2 has 4, and ls3 has 3              
           |2         |10002   |4                   |6               Same issue, this should be 4.              
SELECT
  wh.WHSE_SYSID AS whseSysId,
  (SELECT
    SUM(loc.PL_COUNT)
  FROM ROOM rm
  INNER JOIN LOCATIONS loc
    ON rm.ROOM_SYSID = loc.ROOM_SYSID
  WHERE loc.PL_COUNT > 0
  AND rm.WHSE_SYSID = :whseSysId)
  AS availableFootprints,
  SUM(
  BIGINT(
  ROUND((SELECT
    SUM(CASE
      WHEN st.INVTRY_PALLET_STACK_SYSID IS NULL THEN 1
      ELSE 0.5
    END)
  FROM ROOM rm
  INNER JOIN LOCATIONS loc
    ON rm.ROOM_SYSID =
    loc.ROOM_SYSID
  INNER JOIN INVTRY_PALLET_DTL p
    ON loc.LOC_SYSID =
    p.LOC_SYSID
  LEFT JOIN INVTRY_PALLET_STACK st
    ON p.WHSE_SYSID = st.WHSE_SYSID
    AND (p.INB_LPN =
    st.MASTER_INB_LPN
    OR p.INB_LPN = st.INB_LPN)
  WHERE rm.WHSE_SYSID = :whseSysId), 0
  )
  )
  ) AS usedFootprints
FROM WHSE wh
WHERE wh.WHSE_SYSID = :whseSysId
GROUP BY wh.WHSE_SYSID,
         wh.WHSE_NAME; 

1 个答案:

答案 0 :(得分:0)

我建议“首先考虑加入”(即通过连接寻找包含数据的方式,而不是在select子句中使用子查询)。

我就是这样做的。利用现有的子查询但将它们推送到FROM子句中,为此我们需要一种连接方式,因此它们现在都是GROUP BY rm.WHSE_SYSID,以便结果可以连接到wh.WHSE_SYSID。请注意,因此您不需要在绑定变量中使用这么多where子句:whseSysId(优化器会为您排序)。

将所有数据源移动到FROM子句后,只需使用列别名作为所需的case表达式。更简单。 (也可能更快。)

SELECT
      wh.WHSE_SYSID
    , wh.WHSE_NAME
    , loc.availableFootprints
    , rm.usedFootprints
    , case
          when rm.usedFootprints > loc.availableFootprints then loc.availableFootprints
          else rm.usedFootprints 
      end AS Whatever
FROM WHSE wh
LEFT JOIN (
      SELECT
            rm.WHSE
          , SUM(loc.PL_COUNT) AS availableFootprints
      FROM ROOM rm
      INNER JOIN LOCATIONS loc ON rm.ROOM_SYSID = loc.ROOM_SYSID
      WHERE loc.PL_COUNT > 0
      GROUP BY rm.WHSE_SYSID
) loc ON wh.WHSE_SYSID = loc.WHSE_SYSID
LEFT JOIN (
      SELECT
            rm.WHSE_SYSID
          , SUM(CASE
                  WHEN st.INVTRY_PALLET_STACK_SYSID IS NULL
                  THEN 1
                  ELSE 0.5 END) AS usedFootprints
      FROM ROOM rm
      INNER JOIN LOCATIONS loc ON rm.ROOM_SYSID = loc.ROOM_SYSID
      INNER JOIN INVTRY_PALLET_DTL p ON loc.LOC_SYSID = p.LOC_SYSID
      LEFT JOIN INVTRY_PALLET_STACK st ON p.WHSE_SYSID = st.WHSE_SYSID
            AND (p.INB_LPN = st.MASTER_INB_LPN OR p.INB_LPN = st.INB_LPN)
      GROUP BY rm.WHSE_SYSID
) rm ON wh.WHSE_SYSID = rm.WHSE_SYSID
WHERE wh.WHSE_SYSID = :whseSysId
;

我使用了LEFT JOINS,因为我不知道你的数据。如果任何子查询加入WHSE时可能会导致NULL,因为没有连接的行,那么您可能必须将COALESCE()引入case表达式,仅作为示例:< / p>

    , coalesce(case
          when rm.usedFootprints > loc.availableFootprints then loc.availableFootprints
          else rm.usedFootprints 
      end,0) AS Whatever