SQL - SELECT LEFT JOIN删除行而不是列中的NULL值

时间:2017-05-31 08:20:33

标签: sql select null db2 left-join

我有这个SQL查询,它返回以下表:

    select tk1.ticketid,tk1.ownergroup,tk1.CHANGEDATE as dateentered 
    from tkstatus as tk1
    where TK1.TICKETID='SR4402' and ownergroup is not null
    ORDER BY  dateentered

TICKETID    OWNERGROUP                 DATEENTERED
SR4402      CONTROLDESK-ESB        2017-05-17 14:01:32
SR4402      IT-ZAŠTITA             2017-05-24 13:11:34
SR4402      IT-PODRŠKA             2017-05-24 13:30:57
SR4402      IT-ZAŠTITA             2017-05-24 13:46:17
SR4402      IT-PODRŠKA             2017-05-24 13:52:52
SR4402      IT-ZAŠTITA             2017-05-24 14:12:32

TKSTATUS表具有整数主列TKSTATUSID,对于每一行都是唯一的,每一行都有较大的下一个值。

现在,我希望在该记录中找到的每一行EXITED该组,这意味着该组是下一组的时间。 所以基本上对于这个表我应该再有6行,但最后一行应该有那个列DATEEXITED NULL,因为它仍然在那个组中。 所以我写了这个查询:

select tk1.ticketid,tk1.status,tk1.ownergroup,
tk1.CHANGEDATE as dateentered,tk2.changedate as dateexited  
from tkstatus as    tk1
left outer join tkstatus as tk2 on tk2.ticketid=tk1.ticketid
where 
tk2.tkstatusid in (
    SELECT MIN(tk3.TKSTATUSID) 
    FROM TKSTATUS as tk3
    WHERE tk3.TICKETID=tk2.ticketid AND tk3.ownergroup is not null 
    and tk3.ownergroup!=tk1.ownergroup AND tk3.CHANGEDATE>tk1.changedate
)    
AND TK1.TICKETID='SR4402' 
ORDER BY  dateentered

这会返回5行而不是6行! 我希望第6行有列DATEEXITED null

TICKETID      OWNERGROUP          DATEENTERED         DATEEXITED
SR4402     CONTROLDESK-ESB    2017-05-17 14:01:32   2017-05-24 13:11:34
SR4402       IT-ZAŠTITA       2017-05-24 13:11:34   2017-05-24 13:30:57
SR4402       IT-PODRŠKA       2017-05-24 13:30:57   2017-05-24 13:46:17
SR4402       IT-ZAŠTITA       2017-05-24 13:46:17   2017-05-24 13:52:52
SR4402       IT-PODRŠKA       2017-05-24 13:52:52   2017-05-24 14:12:32

我想以某种方式拥有这样的最后一行

SR4402      IT-ZAŠTITA             2017-05-24 14:12:32   NULL

重要说明:

  1. TKSTATUSIDTKSTATUS表的主要唯一列

  2. 之前我曾尝试TKSTATUSID JOIN ON之后IN,但之后又返回了SQLSTATE错误42972,因为我无法MIN和{{1}在JOIN之后。

  3. 所以这不起作用(返回错误)。

     left outer join tkstatus as tk2 on 
          tk2.ticketid=tk1.ticketid
     and  tk2.tkstatusid in (
          SELECT  MIN(tk3.TKSTATUSID)
          FROM    TKSTATUS as tk3
          WHERE   tk3.TICKETID=tk2.ticketid
              AND tk3.ownergroup is not null 
              and tk3.ownergroup!=tk1.ownergroup
              and tk3.CHANGEDATE>tk1.changedate)
    

2 个答案:

答案 0 :(得分:1)

您误解了OUTER JOIN的工作原理。 JOIN条件将包括OUTER表中缺少的行。

left outer join tkstatus as tk2 on tk2.ticketid=tk1.ticketid

因此,如果您遗漏了给定tk2行的tk1行,tk1仍会包含在内,但该行的所有tk2值都为{{ 1}}。

您已经表明情况并非如此,建议不必使用OUTER JOIN。

请注意,WHERE子句实际上是在 连接后应用 的过滤器。如果您按如下所示更改SELECT列并注释掉WHERE子句,则应该观察问题。

NULL

您的WHERE子句要求SELECT tk1.ticketid, tk1.status, tk1.ownergroup, tk1.CHANGEDATE as dateentered, tk2.changedate as dateexited, tk2.tkstatusid, ( SELECT MIN(tk3.TKSTATUSID) FROM TKSTATUS as tk3 WHERE tk3.TICKETID=tk2.ticketid AND tk3.ownergroup is not null and tk3.ownergroup!=tk1.ownergroup AND tk3.CHANGEDATE>tk1.changedate ) as MinTk3StatusId /* Rest of your query. .... Spelt out because apparently it wasn't obvious enough! */ 等于子查询返回的值。 (请注意,使用tk2.tkstatusid毫无意义,因为子查询只返回单个聚合值。)

毫无疑问,您会发现对于WHERE子句过滤掉的行,最后两列不一样。

实际上,我想我已经弄明白你要做什么了。它看起来像一个自联接来确定选择中下一个项目的ChangeDate。通过使用子查询列,可以显着简化您的查询。

IN

然而,使用"窗口或排名"会更有效率。特征。我不知道DB2是否支持它或它将使用什么语法。但如果我提出的解决方案不够快,请随时进一步调查。

答案 1 :(得分:1)

您的问题是加入后的where语句。我不知道你是否必须使用联接,但是如果你想使用lead生成你的结果,你可以简单地使用:

select ticketid,ownergroup,CHANGEDATE as dateentered, 
lead(CHANGEDATE) over (partition by TICKETID order by CHANGEDATE) as dateexited
from tkstatus as tk1
where TK1.TICKETID='SR4402' and ownergroup is not null
ORDER BY dateentered