我有一个关于使用 UNION ALL 和左外连接的问题。我想要实现的是获取项目总成本以及其他几个领域,但同时我想要很少的其他领域,如零件,来自其他 tables 的直接材料与 Union All 结合。它正在获取项目成本和左外连接子查询之外的所有字段,但由于某种原因,它没有获取包含在连接内的列。
SELECT COUNT(EVT_C) AS NumWO,
PRJ_C AS Project,
PRJ_DESC AS ProjectDescription,
PRJ_S AS Status,
PRJ_DES AS MS,
PRJ_UDF03 AS SP,
SUM(Cost.Total) AS TotalIntLabour,
FROM R5PRJ
LEFT OUTER JOIN R5E ON EVT_PRJ = PRJ_CODE
LEFT OUTER JOIN (
SELECT
BOO_COST AS Total,
EVT_PRJ AS Project,
CAST(BOO_SQLI AS NVARCHAR(400)) AS SystemReference,
BOO_E AS DateEntered,
'Part' AS RType,
'Direct Materials' AS Type
FROM R5BOO
LEFT OUTER JOIN R5E ON EVT_C = BOO_E
WHERE EVT_PRJ IS NOT NULL
UNION ALL
SELECT
TRL_PRICE*TRL_QTY AS Total,
EVT_PRJ AS Project,
TRL_T+'+'+TRL_P AS SystemReference,
TRL_D AS DateEntered,
'Part' AS RType,
'Direct Materials' AS Type
FROM R5TR
LEFT OUTER JOIN R5E ON TRL_E = EVT_C
LEFT OUTER JOIN R5O ON OBJ_C = EVT_OBJ
WHERE TRL_IO = 0 AND TRL_R IN ('RECV','RETN')
UNION ALL
SELECT
TRL_PRICE*TRL_QTY AS Total,
EVT_PRJ AS Project,
TRL_T+'+'+TRL_P AS SystemReference,
TRL_D AS DateEntered,
'Part' AS RType,
'Direct Materials' AS Type
FROM R5TR
LEFT OUTER JOIN R5E ON TRL_E = EVT_C
LEFT OUTER JOIN R5O ON OBJ_C = EVT_OBJ
WHERE TRL_E IS NOT NULL AND TRL_R = 'I' AND TRL_IO = -1
) AS Cost ON Cost.Project = PRJ_C
GROUP BY PRJ_C,PRJ_D,PRJ_S,PRJ_D,PRJUDF03,PRJ_ACTBUD,
PRJ_ORIGBUD,PRJ_UDF01,PRJ_CLASS,PRJ_C
回答1
它没有获取包含在 Join 中的列。
您没有在外部查询中选择它们。
SQL 对数据块进行操作。 table 是输入 FROM 的数据块。查询的输出也是可以输入 FROM 的数据块。
Person table 有 3 列;姓名、生日、身高。
当你写:
SELECT name
FROM person
你得到的只是名称,即使 table 还有另外两列
当你写:
SELECT name
FROM (
SELECT name, height
FROM person
)x
你不会突然得到姓名和身高。您说您只希望 Name 在最终执行的 SELECT (最上面的)中。仅仅因为您在内部查询中提到高度并不意味着它显示为外部查询的输出。内部查询的输出被馈送到外部查询中,而 out 查询不选择 Height 列..就像在 table 名称用于
SELECT name --doesn't mention height
FROM person --even though this has height
这只是“输入数据块”(在本例中为 Person table)和“输出数据块”(在本例中为一个输出反馈给您)
在此查询中:
SELECT name --also doesn't mention height
FROM (
SELECT name, height --even though this has height
FROM person
)x
我们有“来自 table 人的 3 列输入数据块变为 2 列宽输出”,即返回给您的“2 列输入数据块变为 1 列宽输出”
在外部查询中,您只能引用由内部/子查询选择的列,并使用您为子查询提供的别名来引用它们。任何联合集中的第一个查询定义整个联合集的列名
就像子查询在查询期间运行并临时变成 table 一样,因此:
SELECT sq.x
FROM (
SELECT name as x
FROM Person
UNION ALL
SELECT building_name
FROM address
) sq
在这里您可以看到执行联合的子查询已别名为 sq
。第一个查询采用人名并将其别名为 x
。 union 的第二个查询从地址 table 中提取了一个建筑物名称,但该名称对列的名称没有影响。由于联合集中的第一个查询,该列被称为 x
因此,您最终会得到一个您称为 sq.x
的列,其中充满了人和建筑物名称的混合
在外部查询中,您不能在子查询中引用任何列或 tables 的任何名称;子查询运行并且它选择的列成为它被别名的数据块中的列。任何未选择的东西都消失了。如果您需要使用某些东西,您必须选择它:
SELECT sq.x
FROM (
SELECT name as x, age as y
FROM Person
UNION ALL
SELECT building_name, YEAR(GetUtcDate()) - building_built_year
FROM address
) sq
WHERE
sq.y > 50
这将获取所有 50 岁以上的人或建筑物:人查询别名年龄为 y
,外部查询使用 y
。计算建筑年龄的公式没有别名;由于第一个查询,它进入 y
列