SQL OUTER JOIN 返回一些空记录 - 为什么?

SQL OUTER JOIN returning some empty records - why?

我有一个 table project p 和一个 table invoice i,它们都有一个 project_id 字段。我想要一个结果集,其中包括来自 project 的所有 project_id,其中 i.status = "Active",还包括来自 invoice 的所有 project_id,其中 invoice_date > 2016-01-01 。这是我到目前为止尝试过的查询。

SELECT
    p.project_id
FROM
    (SELECT project_id
        FROM project 
        WHERE status = 'Active') p
FULL OUTER JOIN
    (SELECT DISTINCT project_id
        FROM invoice 
        WHERE CONVERT(varchar(10),invoice_date, 20) > '2016-01-01') i
ON i.project_id = p.project_id

projects 中约有 80 个项目的状态为有效,invoice 中约有 120 个项目自 2016 年 1 月 1 日起已开具发票。上面的查询 returns 大约 140 条记录,听起来不错(一些未开发票的活动项目,以及一些非活动的开发票项目)。问题是查询有大约一半的 project_id 为空(NULL?)。就好像它没有从 invoice 中拉入 project_id。请帮我更正一下。

这是结果集的一小段数组...

...
[10] => Array
    (
        [project_id] => 
    )

[11] => Array
    (
        [project_id] => C00F2097-CD36-4497-8B26-0BF59F90B1EA
    )

[12] => Array
    (
        [project_id] => 217F3370-50F2-457E-A4F5-0C09F12E654A
    )

[13] => Array
    (
        [project_id] => 
    )

[14] => Array
    (
        [project_id] => B1A06823-73C8-4691-A3D6-0E1A234516B3
etc...

改为

SELECT coalesce(p.project_id, i.project_id) as project_id 

并且您不会有任何空值。空值是发票中的值而不是项目中的值。

你的描述简直就是在大喊"use UNION, use UNION"!

SELECT p.project_id
FROM project p
WHERE p.status = 'Active'
UNION  -- On purpose to remove duplicates
SELECT i.project_id
FROM invoice i
WHERE i.invoice_date > '2016-01-01';

注意:无需将日期转换为字符串即可与常量值进行比较。事实上,这不是一个好主意(它阻止了索引的使用)。

您也可以使用 UNION ALL 来表达这一点。这可能是获得所需内容的最便宜的方法(假设 table 具有适当的索引):

SELECT p.project_id
FROM project p
WHERE p.status = 'Active'
UNION ALL
SELECT i.project_id
FROM invoice i
WHERE invoice_date > '2016-01-01' AND
      NOT EXISTS (SELECT 1
                  FROM project p2
                  WHERE p2.project_id = i.project_id AND p.status = 'Active'
                 );

在这种情况下,您可能需要 select distinctinvoice table 如果一个项目可以有多个索引。