我有一个表project p
和一个表invoice i
,两者都有一个project_id字段。我想要一个结果集,其中包含来自project
i.status = "Active"
的所有project_ids,其中还包括来自invoice
invoice_date > 2016-01-01
的所有project_ids。这是我到目前为止所尝试的查询。
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-01-01开具发票。上面的查询返回大约140条记录,这听起来是正确的(一些非发票的活动项目,以及一些非活动的发票项目)。问题是查询有大约一半的project_ids为空(NULL?)。它似乎没有从invoice
中提取project_ids。请帮我纠正一下。
以下是结果集的一小段作为数组...
...
[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...
答案 0 :(得分:3)
您的描述只是大喊“使用UNION
,使用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
对此进行说明。这可能是获得您想要的最便宜的方式(假设表有适当的索引):
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 distinct
表中可能需要invoice
。
答案 1 :(得分:2)
更改为
SELECT coalesce(p.project_id, i.project_id) as project_id
,您将不会有任何空值。空值是发票中的值,但不是项目。