Sql 在外部联接到计数表时完成缺少的行

Sql 在外部联接到计数表时完成缺少的行,sql,oracle,Sql,Oracle,我有一个问题,外部联接没有提供足够的空行 业务环境是用户开始并有望完成在线测试。每个用户可以多次尝试每个测试 我试图报告每个用户启动/完成每个测试的次数。特别是,对于每个至少尝试过一次测试的用户,我想为每个测试显示一行计数,即使是他们根本没有尝试过的测试 测试表非常简单 ID NAME -- ---- 1 Test 1 2 Test 2 进度表提供了测试和用户组合的计数 TEST_ID USER_ID NUM_TIMES_STARTED

我有一个问题,外部联接没有提供足够的空行

业务环境是用户开始并有望完成在线测试。每个用户可以多次尝试每个测试

我试图报告每个用户启动/完成每个测试的次数。特别是,对于每个至少尝试过一次测试的用户,我想为每个测试显示一行计数,即使是他们根本没有尝试过的测试

测试表非常简单

    ID  NAME
    --  ----
    1   Test 1
    2   Test 2
进度表提供了测试和用户组合的计数

    TEST_ID  USER_ID  NUM_TIMES_STARTED  NUM_TIMES_FINISHED
    -------  -------- -----------------  ------------------
    1        Alice    2                  1
    1        Bob      1                  0    
我想看到的是,第二行和第四行是关键行:

    USER_ID  TEST_NAME  TIMES_STARTED  TIMES_FINISHED
    -------  ---------  -------------  --------------
    Alice    Test 1     2              1
    Alice    Test 2     0              0
    Bob      Test 1     1              0
    Bob      Test 2     0              0
我的尝试是:

    SELECT p.user_id, t.name, COALESCE(p.num_times_started, 0), 
        COALESCE(p.num_times_finished, 0)
    FROM test t
    LEFT OUTER JOIN progress p
    ON t.id = p.test_id
    ORDER BY p.user_id, t.id
但是对于测试2,这不会重复丢失的行,每个用户一次,我只会多返回一行

    USER_ID  TEST_NAME  TIMES_STARTED  TIMES_FINISHED
    -------  ---------  -------------  --------------
    Alice    Test 1     2              1
    Bob      Test 1     1              0
    (null)   Test 2     0              0
我缺少的是如何在代理级别应用外部联接生成的额外行,而不是整个数据集

数据库服务器是Oracle 9i。我无法对表结构进行任何更改


非常感谢您的想法。

交叉加入CTE,左加入数据

with CTE as
(
select distinct user_id, test_name
from Progress
cross join test
)
select CTE.*, 
       COALESCE(p.num_times_started, 0), 
       COALESCE(p.num_times_finished, 0)
from CTE
left join progress p
  on p.user_id = CTE.user_ID
  and p.test_id = CTE.test_id

在CTE中交叉连接,左连接数据

with CTE as
(
select distinct user_id, test_name
from Progress
cross join test
)
select CTE.*, 
       COALESCE(p.num_times_started, 0), 
       COALESCE(p.num_times_finished, 0)
from CTE
left join progress p
  on p.user_id = CTE.user_ID
  and p.test_id = CTE.test_id
只需交叉加入参加测试的不同用户:

SELECT u.user_id,
       t.test_name,
       COALESCE( p.num_times_started,  0 ) AS num_times_started,
       COALESCE( p.num_times_finished, 0 ) AS num_times_finished
FROM   ( SELECT DISTINCT user_id FROM progress ) u
       CROSS JOIN
       test t
       LEFT OUTER JOIN progress p
       ON ( u.user_id = p.user_id AND t.id = p.test_id )
只需交叉加入参加测试的不同用户:

SELECT u.user_id,
       t.test_name,
       COALESCE( p.num_times_started,  0 ) AS num_times_started,
       COALESCE( p.num_times_finished, 0 ) AS num_times_finished
FROM   ( SELECT DISTINCT user_id FROM progress ) u
       CROSS JOIN
       test t
       LEFT OUTER JOIN progress p
       ON ( u.user_id = p.user_id AND t.id = p.test_id )

值得注意的是,如果您曾经将此数据库升级到10g或更高版本(希望更高),最新的db版本是12.2!,然后,您可以通过使用来实现您的结果,而不必在执行另一个连接和筛选等操作之前磨蹭和交叉连接感谢您提供了出色的链接-只需按用户id添加分区就可以修复我对Oracle 11的第一次尝试。客户机有望在今年升级…值得注意的是,如果您曾经将此数据库升级到10g或更高版本(希望更高),考虑到最新的db版本是12.2!,然后,您可以通过使用来实现您的结果,而不必在执行另一个连接和筛选等操作之前磨蹭和交叉连接感谢您提供了出色的链接-只需按用户id添加分区就可以修复我对Oracle 11的第一次尝试。客户希望今年升级…非常感谢John-非常整洁,它提供了我所需要的。非常感谢John-非常整洁,它提供了我所需要的。