创建具有多个连接的 SQL 视图时出现问题
Problem with creating a SQL view with multiple joins
我正在尝试创建一个视图,它将作为 Excel 在 API 中导出的基础。基本上,它包含的是有关特定项目的信息。可以向所述项目添加计算(这一切都发生在前端的表单上)。这些计算称为 EBIT、EBIT+ 和 OVI。用户可以添加其中一个、两个或全部,因此例如会有只有 EBIT 的项目,也有只有 EBIT 的项目,但也有只有 EBIT+ 和 OVI 的项目。 View 需要 return 项目信息和所有选定的计算在一行中,因此由于用户不会选择某些类型的计算,因此还需要类型安全。
我的观点代码:
CREATE VIEW [Signoff].[ExecelReport_uvw]
AS SELECT
project.ProjectName,
project.CreatedOn,
project.ProjectId,
subCategory.SubCategoryName,
projectStatus.StatusName,
overallCategory.CategoryName,
projectUserResponsible.UserName,
valueImprovementType.ValueImprovementTypeName,
OVI.OverallImprovementTypeName,
project.NameOfSuplier,
improvementCalculation.Baseline,
improvementCalculation.ImpactValue,
project.ContractStartDate,
project.ContractEndDate,
userbusinessController.UserName as businessControllerName,
businessControllerStatus.ApprovalStatusName businessControllerStatus,
userbusinesOwner.UserName as businessOwnerName,
businesOwnerStatus.ApprovalStatusName as businessOwnerStatus,
userbusinessCFO.UserName as businessCFOName,
businessCFOStatus.ApprovalStatusName as businessCFOStatus,
project.IsEbitda,
improvementCalculation.EBITDA
FROM [Signoff].[Project] as project
LEFT JOIN [Signoff].[OverallImprovementType] as OVI on project.OverallImprovementTypeId = OVI.OverallImprovementTypeId
LEFT JOIN [Signoff].[SubCategory] as subCategory on project.GPSubCategory = subCategory.SubCategoryId
LEFT JOIN [Signoff].[Category] as overallCategory on project.GPCategory = overallCategory.CategoryId
LEFT JOIN [Signoff].[ValueImprovementType] as valueImprovementType on project.ValueImprovementTypeId = valueImprovementType.ValueImprovementTypeId
LEFT JOIN [Signoff].[Status] as projectStatus on project.ProjectStatus = projectStatus.StatusId
LEFT JOIN [Signoff].[User] as projectUserResponsible on project.ProjectResponsible = projectUserResponsible.UserId
LEFT JOIN [Signoff].[ProjectUser] as projectUserbusinessControler on project.ProjectId = projectUserbusinessControler.ProjectId AND projectUserbusinessControler.ProjectRoleId = 'A36FC6CD-9ED7-4AA8-B1BE-355E48BDE25A'
LEFT JOIN [Signoff].[User] as userbusinessController on projectUserbusinessControler.ApproverId = userbusinessController.UserId
LEFT JOIN [Signoff].[ApprovalStatus] as businessControllerStatus on projectUserbusinessControler.ApprovalStatusId = businessControllerStatus.ApprovalStatusId
LEFT JOIN [Signoff].[ProjectUser] as projectUserbusinessOwner on project.ProjectId = projectUserbusinessOwner.ProjectId AND projectUserbusinessOwner.ProjectRoleId = 'E1E23E4F-1CA4-4869-9387-43CEDAEBBBB0'
LEFT JOIN [Signoff].[User] as userbusinesOwner on projectUserbusinessOwner.ApproverId = userbusinesOwner.UserId
LEFT JOIN [Signoff].[ApprovalStatus] as businesOwnerStatus on projectUserbusinessOwner.ApprovalStatusId = businesOwnerStatus.ApprovalStatusId
LEFT JOIN [Signoff].[ProjectUser] as projectUserbusinessCFO on project.ProjectId = projectUserbusinessCFO.ProjectId AND projectUserbusinessCFO.ProjectRoleId = 'DA17CF66-1D61-460E-BF87-5D86744DF22A'
LEFT JOIN [Signoff].[User] as userbusinessCFO on projectUserbusinessCFO.ApproverId = userbusinessCFO.UserId
LEFT JOIN [Signoff].[ApprovalStatus] as businessCFOStatus on projectUserbusinessCFO.ApprovalStatusId = businessCFOStatus.ApprovalStatusId
LEFT JOIN [Signoff].[ProjectImprovementCalculation] as projectImprovementCalculation on project.ProjectId = projectImprovementCalculation.ProjectId
LEFT JOIN [Signoff].[ImprovementCalculation] as improvementCalculation on projectImprovementCalculation.ImprovementCalculationId = improvementCalculation.ImprovementCalculationId
改进计算table:
CREATE TABLE [Signoff].[ImprovementCalculation]
(
[ImprovementCalculationId] INT NOT NULL IDENTITY,
[Baseline] INT NOT NULL,
[TotalSpend] INT NOT NULL,
[ImpactValue] INT NOT NULL,
[ImpactPercentage] INT NOT NULL,
[EBITDA] INT NOT NULL,
[CalculationType] VARCHAR (255) NOT NULL
)
GO
ALTER TABLE [Signoff].[ImprovementCalculation]
ADD CONSTRAINT [PK_ImprovemntCalculation] PRIMARY KEY([ImprovementCalculationId]);
GO
项目改进计算table:
CREATE TABLE [Signoff].[ProjectImprovementCalculation]
(
[ProjectImprovementCalculationId] INT NOT NULL IDENTITY,
[ProjectId] UNIQUEIDENTIFIER NOT NULL,
[ImprovementCalculationId] INT NOT NULL,
)
GO
ALTER TABLE [Signoff].[ProjectImprovementCalculation]
ADD CONSTRAINT [PK_ProjectImprovementCalculation] PRIMARY KEY([ProjectImprovementCalculationId]);
GO
ALTER TABLE [Signoff].[ProjectImprovementCalculation]
ADD CONSTRAINT FK_ProjectProjectImprovementCalculation
FOREIGN KEY (ProjectId) REFERENCES [Signoff].[Project](ProjectId);
GO
ALTER TABLE [Signoff].[ProjectImprovementCalculation]
ADD CONSTRAINT FK_ImprovementCalculationProjectImprovementCalculation
FOREIGN KEY (ImprovementCalculationId) REFERENCES [Signoff].[ImprovementCalculation](ImprovementCalculationId);
GO
以防万一,虽然我觉得没必要,项目table:
CREATE TABLE [Signoff].[Project]
(
[ProjectId] UNIQUEIDENTIFIER NOT NULL DEFAULT (NEWID()),
[ProjectName] NVARCHAR(50) NOT NULL,
[LegalEntity] UNIQUEIDENTIFIER NOT NULL,
[ValueImprovementTypeId] INT NOT NULL,
[OverallImprovementTypeId] INT NOT NULL,
[NameOfSuplier] NVARCHAR(50) NOT NULL,
[ContractStartDate] DATE NOT NULL,
[ContractEndDate] DATE NOT NULL,
[GPCategory] UNIQUEIDENTIFIER NOT NULL,
[GPSubCategory] UNIQUEIDENTIFIER NOT NULL,
[ProjectResponsible] UNIQUEIDENTIFIER NOT NULL,
[ProjectNumber] INT,
[FullProjectNumber] VARCHAR(55),
[ProjectStatus] UNIQUEIDENTIFIER NOT NULL DEFAULT '05c2f392-8b69-4915-a166-c4418889f9e8',
[IsCanceled] BIT NULL DEFAULT 0,
[IsEbitda] BIT NOT NULL DEFAULT 0,
[CreatedOn] DATETIME NOT NULL DEFAULT SYSDATETIME()
)
GO
ALTER TABLE [Signoff].[Project]
ADD CONSTRAINT [PK_Project] PRIMARY KEY([ProjectId]);
GO
ALTER TABLE [Signoff].[Project]
ADD CONSTRAINT [FK_ProjectStatus] FOREIGN KEY ([ProjectStatus]) REFERENCES [Signoff].[Status]([StatusId]);
GO
我想出了这个解决方案,但它 return 在 table 中的不同行中的每个计算,我希望所有计算都在一个项目的一行中,所以不是我要找的:
LEFT JOIN [Signoff].[ProjectImprovementCalculation] as projectImprovementCalculation on project.ProjectId = projectImprovementCalculation.ProjectId
LEFT JOIN [Signoff].[ImprovementCalculation] as improvementCalculation on projectImprovementCalculation.ImprovementCalculationId = improvementCalculation.ImprovementCalculationId
有人知道怎么做吗?或者我正在以完全错误的方式解决问题?如果我写的信息有点乱,有看不懂的地方,我可以改一下。
我假设可用的 CalculationType 值是固定的,每个项目每种类型最多有一个改进计算,并且您希望为每种计算类型定义固定的专用列 BaseLine 和 ImpactValue。
一种方法是使用嵌套联接,这将有效地对每种计算类型左联接 ProjectImprovementCalculation 和 ImprovementCalculation 的内部联接组合一次。然后可以在最终 select 列表中单独引用每个结果。
类似于:
SELECT ...
IC_AAA.BaseLine, IC_AAA.ImpactValue,
IC_BBB.BaseLine, IC_BBB.ImpactValue,
...
FROM ...
LEFT JOIN Signoff.ProjectImprovementCalculation as PIC_AAA
JOIN Signoff.ImprovementCalculation as IC_AAA
ON IC_AAA.ImprovementCalculationId = PIC_AAA.ImprovementCalculationId
AND IC_AAA.CalculationType = 'AAA'
ON PIC_AAA.ProjectId = project.ProjectId
LEFT JOIN Signoff.ProjectImprovementCalculation as PIC_BBB
JOIN Signoff.ImprovementCalculation as IC_BBB
ON IC_BBB.ImprovementCalculationId = PIC_BBB.ImprovementCalculationId
AND IC_BBB.CalculationType = 'BBB'
ON PIC_BBB.ProjectId = project.ProjectId
...
语法有点奇怪,两个 JOINs
后跟两个 ON
子句。如果允许使用括号会更清楚,但(据我所知)这不是语法的一部分。
有多种替代方法可以实现同样的效果。以下使用 OUTER APPLY
:
SELECT ...
AAA.BaseLine, AAA.ImpactValue,
BBB.BaseLine, BBB.ImpactValue,
...
FROM ...
OUTER APPLY (
SELECT IC.*
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
AND IC.CalculationType = 'AAA'
WHERE PIC.ProjectId = project.ProjectId
) AAA
OUTER APPLY (
SELECT IC.*
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
AND IC.CalculationType = 'BBB'
WHERE PIC.ProjectId = project.ProjectId
) BBB
...
使用通用 Table 表达式 (CTE) 可以减少一些重复并使查询更具可读性。
;WITH ImprovementCTE AS (
SELECT PIC.ProjectId, IC.*
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
)
SELECT ...
AAA.BaseLine, AAA.ImpactValue,
BBB.BaseLine, BBB.ImpactValue,
...
FROM ...
LEFT JOIN ImprovementCTE AAA
ON AAA.ProjectId = project.ProjectId
AND AAA.CalculationType = 'AAA'
LEFT JOIN ImprovementCTE BBB
ON BBB.ProjectId = project.ProjectId
AND BBB.CalculationType = 'BBB'
...
您也可以尝试在单个 CROSS APPLY
:
中使用 条件聚合
SELECT ...
IC.BaseLineAAA, IC.ImpactValueAAA,
IC.BaseLineBBB, IC.ImpactValueBBB,
...
FROM ...
CROSS APPLY (
SELECT
BaseLineAAA = SUM(CASE WHEN IC.CalculationType = 'AAA' THEN IC.BaseLine),
ImpactValueAAA = SUM(CASE WHEN IC.CalculationType = 'AAA' THEN IC.ImpactValue),
BaseLineBBB = SUM(CASE WHEN IC.CalculationType = 'BBB' THEN IC.BaseLine),
ImpactValueBBB = SUM(CASE WHEN IC.CalculationType = 'BBB' THEN IC.ImpactValue),
...
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
WHERE PIC.ProjectId = project.ProjectId
) IC
我希望还有其他方法,例如使用 PIVOT。
如果以上似乎满足您的需要,您仍应 运行 测试并检查执行计划以查看哪个执行计划最佳。有些人可能倾向于检索所有 ImprovementCalculation 行,即使项目的子集已 selected。
要处理缺失的计算类型,您可以使用 ISNULL()
函数提供默认值。如果您需要在其他数字结果中强制使用空白值,您可能需要使用类似 ISNULL(CONVERT(VARCHAR(50), result), '')
.
的内容
我正在尝试创建一个视图,它将作为 Excel 在 API 中导出的基础。基本上,它包含的是有关特定项目的信息。可以向所述项目添加计算(这一切都发生在前端的表单上)。这些计算称为 EBIT、EBIT+ 和 OVI。用户可以添加其中一个、两个或全部,因此例如会有只有 EBIT 的项目,也有只有 EBIT 的项目,但也有只有 EBIT+ 和 OVI 的项目。 View 需要 return 项目信息和所有选定的计算在一行中,因此由于用户不会选择某些类型的计算,因此还需要类型安全。
我的观点代码:
CREATE VIEW [Signoff].[ExecelReport_uvw]
AS SELECT
project.ProjectName,
project.CreatedOn,
project.ProjectId,
subCategory.SubCategoryName,
projectStatus.StatusName,
overallCategory.CategoryName,
projectUserResponsible.UserName,
valueImprovementType.ValueImprovementTypeName,
OVI.OverallImprovementTypeName,
project.NameOfSuplier,
improvementCalculation.Baseline,
improvementCalculation.ImpactValue,
project.ContractStartDate,
project.ContractEndDate,
userbusinessController.UserName as businessControllerName,
businessControllerStatus.ApprovalStatusName businessControllerStatus,
userbusinesOwner.UserName as businessOwnerName,
businesOwnerStatus.ApprovalStatusName as businessOwnerStatus,
userbusinessCFO.UserName as businessCFOName,
businessCFOStatus.ApprovalStatusName as businessCFOStatus,
project.IsEbitda,
improvementCalculation.EBITDA
FROM [Signoff].[Project] as project
LEFT JOIN [Signoff].[OverallImprovementType] as OVI on project.OverallImprovementTypeId = OVI.OverallImprovementTypeId
LEFT JOIN [Signoff].[SubCategory] as subCategory on project.GPSubCategory = subCategory.SubCategoryId
LEFT JOIN [Signoff].[Category] as overallCategory on project.GPCategory = overallCategory.CategoryId
LEFT JOIN [Signoff].[ValueImprovementType] as valueImprovementType on project.ValueImprovementTypeId = valueImprovementType.ValueImprovementTypeId
LEFT JOIN [Signoff].[Status] as projectStatus on project.ProjectStatus = projectStatus.StatusId
LEFT JOIN [Signoff].[User] as projectUserResponsible on project.ProjectResponsible = projectUserResponsible.UserId
LEFT JOIN [Signoff].[ProjectUser] as projectUserbusinessControler on project.ProjectId = projectUserbusinessControler.ProjectId AND projectUserbusinessControler.ProjectRoleId = 'A36FC6CD-9ED7-4AA8-B1BE-355E48BDE25A'
LEFT JOIN [Signoff].[User] as userbusinessController on projectUserbusinessControler.ApproverId = userbusinessController.UserId
LEFT JOIN [Signoff].[ApprovalStatus] as businessControllerStatus on projectUserbusinessControler.ApprovalStatusId = businessControllerStatus.ApprovalStatusId
LEFT JOIN [Signoff].[ProjectUser] as projectUserbusinessOwner on project.ProjectId = projectUserbusinessOwner.ProjectId AND projectUserbusinessOwner.ProjectRoleId = 'E1E23E4F-1CA4-4869-9387-43CEDAEBBBB0'
LEFT JOIN [Signoff].[User] as userbusinesOwner on projectUserbusinessOwner.ApproverId = userbusinesOwner.UserId
LEFT JOIN [Signoff].[ApprovalStatus] as businesOwnerStatus on projectUserbusinessOwner.ApprovalStatusId = businesOwnerStatus.ApprovalStatusId
LEFT JOIN [Signoff].[ProjectUser] as projectUserbusinessCFO on project.ProjectId = projectUserbusinessCFO.ProjectId AND projectUserbusinessCFO.ProjectRoleId = 'DA17CF66-1D61-460E-BF87-5D86744DF22A'
LEFT JOIN [Signoff].[User] as userbusinessCFO on projectUserbusinessCFO.ApproverId = userbusinessCFO.UserId
LEFT JOIN [Signoff].[ApprovalStatus] as businessCFOStatus on projectUserbusinessCFO.ApprovalStatusId = businessCFOStatus.ApprovalStatusId
LEFT JOIN [Signoff].[ProjectImprovementCalculation] as projectImprovementCalculation on project.ProjectId = projectImprovementCalculation.ProjectId
LEFT JOIN [Signoff].[ImprovementCalculation] as improvementCalculation on projectImprovementCalculation.ImprovementCalculationId = improvementCalculation.ImprovementCalculationId
改进计算table:
CREATE TABLE [Signoff].[ImprovementCalculation]
(
[ImprovementCalculationId] INT NOT NULL IDENTITY,
[Baseline] INT NOT NULL,
[TotalSpend] INT NOT NULL,
[ImpactValue] INT NOT NULL,
[ImpactPercentage] INT NOT NULL,
[EBITDA] INT NOT NULL,
[CalculationType] VARCHAR (255) NOT NULL
)
GO
ALTER TABLE [Signoff].[ImprovementCalculation]
ADD CONSTRAINT [PK_ImprovemntCalculation] PRIMARY KEY([ImprovementCalculationId]);
GO
项目改进计算table:
CREATE TABLE [Signoff].[ProjectImprovementCalculation]
(
[ProjectImprovementCalculationId] INT NOT NULL IDENTITY,
[ProjectId] UNIQUEIDENTIFIER NOT NULL,
[ImprovementCalculationId] INT NOT NULL,
)
GO
ALTER TABLE [Signoff].[ProjectImprovementCalculation]
ADD CONSTRAINT [PK_ProjectImprovementCalculation] PRIMARY KEY([ProjectImprovementCalculationId]);
GO
ALTER TABLE [Signoff].[ProjectImprovementCalculation]
ADD CONSTRAINT FK_ProjectProjectImprovementCalculation
FOREIGN KEY (ProjectId) REFERENCES [Signoff].[Project](ProjectId);
GO
ALTER TABLE [Signoff].[ProjectImprovementCalculation]
ADD CONSTRAINT FK_ImprovementCalculationProjectImprovementCalculation
FOREIGN KEY (ImprovementCalculationId) REFERENCES [Signoff].[ImprovementCalculation](ImprovementCalculationId);
GO
以防万一,虽然我觉得没必要,项目table:
CREATE TABLE [Signoff].[Project]
(
[ProjectId] UNIQUEIDENTIFIER NOT NULL DEFAULT (NEWID()),
[ProjectName] NVARCHAR(50) NOT NULL,
[LegalEntity] UNIQUEIDENTIFIER NOT NULL,
[ValueImprovementTypeId] INT NOT NULL,
[OverallImprovementTypeId] INT NOT NULL,
[NameOfSuplier] NVARCHAR(50) NOT NULL,
[ContractStartDate] DATE NOT NULL,
[ContractEndDate] DATE NOT NULL,
[GPCategory] UNIQUEIDENTIFIER NOT NULL,
[GPSubCategory] UNIQUEIDENTIFIER NOT NULL,
[ProjectResponsible] UNIQUEIDENTIFIER NOT NULL,
[ProjectNumber] INT,
[FullProjectNumber] VARCHAR(55),
[ProjectStatus] UNIQUEIDENTIFIER NOT NULL DEFAULT '05c2f392-8b69-4915-a166-c4418889f9e8',
[IsCanceled] BIT NULL DEFAULT 0,
[IsEbitda] BIT NOT NULL DEFAULT 0,
[CreatedOn] DATETIME NOT NULL DEFAULT SYSDATETIME()
)
GO
ALTER TABLE [Signoff].[Project]
ADD CONSTRAINT [PK_Project] PRIMARY KEY([ProjectId]);
GO
ALTER TABLE [Signoff].[Project]
ADD CONSTRAINT [FK_ProjectStatus] FOREIGN KEY ([ProjectStatus]) REFERENCES [Signoff].[Status]([StatusId]);
GO
我想出了这个解决方案,但它 return 在 table 中的不同行中的每个计算,我希望所有计算都在一个项目的一行中,所以不是我要找的:
LEFT JOIN [Signoff].[ProjectImprovementCalculation] as projectImprovementCalculation on project.ProjectId = projectImprovementCalculation.ProjectId
LEFT JOIN [Signoff].[ImprovementCalculation] as improvementCalculation on projectImprovementCalculation.ImprovementCalculationId = improvementCalculation.ImprovementCalculationId
有人知道怎么做吗?或者我正在以完全错误的方式解决问题?如果我写的信息有点乱,有看不懂的地方,我可以改一下。
我假设可用的 CalculationType 值是固定的,每个项目每种类型最多有一个改进计算,并且您希望为每种计算类型定义固定的专用列 BaseLine 和 ImpactValue。
一种方法是使用嵌套联接,这将有效地对每种计算类型左联接 ProjectImprovementCalculation 和 ImprovementCalculation 的内部联接组合一次。然后可以在最终 select 列表中单独引用每个结果。
类似于:
SELECT ...
IC_AAA.BaseLine, IC_AAA.ImpactValue,
IC_BBB.BaseLine, IC_BBB.ImpactValue,
...
FROM ...
LEFT JOIN Signoff.ProjectImprovementCalculation as PIC_AAA
JOIN Signoff.ImprovementCalculation as IC_AAA
ON IC_AAA.ImprovementCalculationId = PIC_AAA.ImprovementCalculationId
AND IC_AAA.CalculationType = 'AAA'
ON PIC_AAA.ProjectId = project.ProjectId
LEFT JOIN Signoff.ProjectImprovementCalculation as PIC_BBB
JOIN Signoff.ImprovementCalculation as IC_BBB
ON IC_BBB.ImprovementCalculationId = PIC_BBB.ImprovementCalculationId
AND IC_BBB.CalculationType = 'BBB'
ON PIC_BBB.ProjectId = project.ProjectId
...
语法有点奇怪,两个 JOINs
后跟两个 ON
子句。如果允许使用括号会更清楚,但(据我所知)这不是语法的一部分。
有多种替代方法可以实现同样的效果。以下使用 OUTER APPLY
:
SELECT ...
AAA.BaseLine, AAA.ImpactValue,
BBB.BaseLine, BBB.ImpactValue,
...
FROM ...
OUTER APPLY (
SELECT IC.*
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
AND IC.CalculationType = 'AAA'
WHERE PIC.ProjectId = project.ProjectId
) AAA
OUTER APPLY (
SELECT IC.*
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
AND IC.CalculationType = 'BBB'
WHERE PIC.ProjectId = project.ProjectId
) BBB
...
使用通用 Table 表达式 (CTE) 可以减少一些重复并使查询更具可读性。
;WITH ImprovementCTE AS (
SELECT PIC.ProjectId, IC.*
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
)
SELECT ...
AAA.BaseLine, AAA.ImpactValue,
BBB.BaseLine, BBB.ImpactValue,
...
FROM ...
LEFT JOIN ImprovementCTE AAA
ON AAA.ProjectId = project.ProjectId
AND AAA.CalculationType = 'AAA'
LEFT JOIN ImprovementCTE BBB
ON BBB.ProjectId = project.ProjectId
AND BBB.CalculationType = 'BBB'
...
您也可以尝试在单个 CROSS APPLY
:
SELECT ...
IC.BaseLineAAA, IC.ImpactValueAAA,
IC.BaseLineBBB, IC.ImpactValueBBB,
...
FROM ...
CROSS APPLY (
SELECT
BaseLineAAA = SUM(CASE WHEN IC.CalculationType = 'AAA' THEN IC.BaseLine),
ImpactValueAAA = SUM(CASE WHEN IC.CalculationType = 'AAA' THEN IC.ImpactValue),
BaseLineBBB = SUM(CASE WHEN IC.CalculationType = 'BBB' THEN IC.BaseLine),
ImpactValueBBB = SUM(CASE WHEN IC.CalculationType = 'BBB' THEN IC.ImpactValue),
...
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
WHERE PIC.ProjectId = project.ProjectId
) IC
我希望还有其他方法,例如使用 PIVOT。
如果以上似乎满足您的需要,您仍应 运行 测试并检查执行计划以查看哪个执行计划最佳。有些人可能倾向于检索所有 ImprovementCalculation 行,即使项目的子集已 selected。
要处理缺失的计算类型,您可以使用 ISNULL()
函数提供默认值。如果您需要在其他数字结果中强制使用空白值,您可能需要使用类似 ISNULL(CONVERT(VARCHAR(50), result), '')
.