Oracle 12C SQL-使用联接填充缺少的结果

问题描述

我有下面的数据表(例如,简化了)

TEAM    WORKS   TT
TEAM_A  JOB_1   10
TEAM_A  JOB_3   20
TEAM_B  JOB_2   30

我希望得到以下结果

TEAM    WORKS   TT
TEAM_A  JOB_1   10
TEAM_A  JOB_2   NULL
TEAM_A  JOB_3   20
TEAM_B  JOB_1   NULL
TEAM_B  JOB_2   30
TEAM_B  JOB_3   NULL

此结果表需要为每个团队添加未出现在原始数据集中的工作类型,并给出时间值NULL

我尝试使用以下sql,并尝试了多种联接类型,但始终无法获得期望的结果。

WITH BASE AS (
            SELECT 'TEAM_A' AS TEAM,'JOB_1' AS WORKS,10 AS TT FROM DUAL
UNION ALL   SELECT 'TEAM_A' AS TEAM,'JOB_3' AS WORKS,20 AS TT FROM DUAL
UNION ALL   SELECT 'TEAM_B' AS TEAM,'JOB_2' AS WORKS,30 AS TT FROM DUAL
)
SELECT
        BASE.TEAM,BASE.WORKS,BASE.TT
FROM BASE
FULL OUTER JOIN (
                SELECT 'JOB_1' AS WORKS FROM DUAL
    UNION ALL   SELECT 'JOB_2' AS WORKS FROM DUAL
    UNION ALL   SELECT 'JOB_3' AS WORKS FROM DUAL
) WORK_TYPES ON BASE.WORKS = WORK_TYPES.WORKS
;

解决方法

显而易见的解决方案是使用partitioned outer join,这恰好解决了您的问题:

WITH BASE AS (
            SELECT 'TEAM_A' AS TEAM,'JOB_1' AS WORKS,10 AS TT FROM DUAL
UNION ALL   SELECT 'TEAM_A' AS TEAM,'JOB_3' AS WORKS,20 AS TT FROM DUAL
UNION ALL   SELECT 'TEAM_B' AS TEAM,'JOB_2' AS WORKS,30 AS TT FROM DUAL
)
SELECT
        BASE.TEAM,WORK_TYPES.WORKS,BASE.TT
FROM (
                      SELECT 'JOB_1' AS WORKS FROM DUAL
          UNION ALL   SELECT 'JOB_2' AS WORKS FROM DUAL
          UNION ALL   SELECT 'JOB_3' AS WORKS FROM DUAL
     ) WORK_TYPES 
     left JOIN BASE
     partition by (base.team)
     ON BASE.WORKS = WORK_TYPES.WORKS
;

结果:

TEAM   WORKS         TT
------ ----- ----------
TEAM_A JOB_1         10
TEAM_A JOB_2
TEAM_A JOB_3         20
TEAM_B JOB_1
TEAM_B JOB_2         30
TEAM_B JOB_3
,

您可以交叉加入不同的团队并进行工作,然后用left join带到桌上:

select te.team,wo.work,ta.tt
from (select distinct team from mytable) te
cross join (select distinct work from mytable) wo
left join mytable ta
    on ta.team = te.team and ta.work = wo.work
order by te.team,wo.work