我有这个基于日期/星期的表,我需要从中获取每个部门的数据行。 这些行包括多个星期(和/或句号),我试图找到最快的方法。 作为旁注,我使用动态SQL来创建查询,因为我的周和周期是可变的。
目前我的查询如下:
SELECT tblPROJECT_COMPANY_DEPARTMENT.fk_company_department_id
, ISNULL (
(SELECT SUM(employeesweek) * 40
FROM tblCAPACITY_PROJECT as vwCap
INNER JOIN tblPROJECT as vwPro ON vwCap.fk_project_id = vwPro.id
AND vwPro.active = 1
AND vwPro.capacityproject = 1
INNER JOIN tblPROJECT_COMPANY_DEPARTMENT as vwProCD on vwPro.id = vwProCD.fk_project_id
AND vwProCD.fk_company_structure_instance_id = tblPROJECT_COMPANY_DEPARTMENT.fk_company_structure_instance_id
AND vwPro.status = tblPROJECT.status
WHERE vwProCD.fk_company_department_id = tblPROJECT_COMPANY_DEPARTMENT.fk_company_department_id
AND CAST(vwCap.year AS Varchar(4)) + vwCap.weeknumber BETWEEN 201425 AND 201436
), 0) AS Total
, ISNULL ((
SELECT SUM(employeesweek)
FROM tblCAPACITY_PROJECT as vwCap
INNER JOIN tblPROJECT as vwPro ON vwCap.fk_project_id = vwPro.id
AND vwPro.active = 1
AND vwPro.capacityproject = 1
INNER JOIN tblPROJECT_COMPANY_DEPARTMENT as vwProCD on vwPro.id = vwProCD.fk_project_id
AND vwProCD.fk_company_structure_instance_id = tblPROJECT_COMPANY_DEPARTMENT.fk_company_structure_instance_id
AND vwPro.status = tblPROJECT.status
WHERE vwProCD.fk_company_department_id = tblPROJECT_COMPANY_DEPARTMENT.fk_company_department_id
AND vwCap.Year = 2014 AND vwCap.Weeknumber = 25
), 0) AS Week1
, ISNULL ((
SELECT SUM(employeesweek) FROM tblCAPACITY_PROJECT as vwCap
...
), 0) AS Week2
, ISNULL ((
SELECT SUM(employeesweek) FROM tblCAPACITY_PROJECT as vwCap
...
), 0) AS Week3
, ISNULL ((
SELECT ROUND(SUM(employeesweek) / 4, 2,0)
FROM tblCAPACITY_PROJECT as vwCap
INNER JOIN tblPROJECT as vwPro ON vwCap.fk_project_id = vwPro.id AND vwPro.active = 1 AND vwPro.capacityproject = 1
INNER JOIN tblPROJECT_COMPANY_DEPARTMENT as vwProCD on vwPro.id = vwProCD.fk_project_id
AND vwProCD.fk_company_structure_instance_id = tblPROJECT_COMPANY_DEPARTMENT.fk_company_structure_instance_id
AND vwPro.status = tblPROJECT.status
WHERE vwProCD.fk_company_department_id = tblPROJECT_COMPANY_DEPARTMENT.fk_company_department_id
AND vwCap.Year = 2014 AND vwCap.period = 08
), 0) AS Period1
, ISNULL ((
SELECT ROUND(SUM(employeesweek) / 4, 2,0)
...
AND vwCap.Year = 2014 AND vwCap.period = 09
), 0) AS Period2
FROM tblPROJECT
LEFT OUTER JOIN tblCAPACITY_PROJECT ON tblPROJECT.id = tblCAPACITY_PROJECT.fk_project_id
INNER JOIN tblCOMPANY ON tblPROJECT.fk_company_id = tblCOMPANY.id
INNER JOIN tblLOCATION ON tblPROJECT.fk_location_id = tblLOCATION.id
INNER JOIN vwCOMMANDERS ON tblPROJECT.fk_commander_id = vwCOMMANDERS.id
INNER JOIN tblPROJECT_COMPANY_DEPARTMENT ON tblPROJECT.id = tblPROJECT_COMPANY_DEPARTMENT.fk_project_id
INNER JOIN tblCOMPANY_DEPARTMENT ON tblPROJECT_COMPANY_DEPARTMENT.fk_company_department_id = tblCOMPANY_DEPARTMENT.id
INNER JOIN tblCOMPANY_STRUCTURE ON tblCOMPANY_DEPARTMENT.id = tblCOMPANY_STRUCTURE.fk_company_department_id
AND tblCOMPANY_STRUCTURE.[year] = 2014
INNER JOIN tblCOMPANY_BUSINESSUNIT ON tblCOMPANY_STRUCTURE.fk_company_businessunit_id = tblCOMPANY_BUSINESSUNIT.id
WHERE tblPROJECT.active = 1 AND tblPROJECT.capacityproject = 1
AND tblPROJECT_COMPANY_DEPARTMENT.fk_company_structure_instance_id = 38
AND tblPROJECT.status = 'D'
AND tblPROJECT_COMPANY_DEPARTMENT.fk_company_department_id = 956
GROUP BY tblPROJECT_COMPANY_DEPARTMENT.fk_company_department_id, tblCOMPANY_DEPARTMENT.name,
tblPROJECT_COMPANY_DEPARTMENT.fk_company_structure_instance_id, tblPROJECT.status
这给出了以下输出:
fk_company_department_id Total Week1 Week2 Week3 Period1 Period2
----------------------------------------------------------------
956 24240 28 28 34 28,5 91,75
(我用......替换了一些重复的代码)
经过一番搜索,我发现将子查询转换为连接可能会有所帮助,所以我这样做了:
SELECT DISTINCT tblPROJECT_COMPANY_DEPARTMENT.fk_company_department_id,
tblCOMPANY_DEPARTMENT.name as companydepartmentname,
sTotal.total, sWeek1.Week1, sWeek2.Week2, sWeek3.Week3,
sPeriod1.Period1, sPeriod2.Period2
FROM tblPROJECT
LEFT OUTER JOIN tblCAPACITY_PROJECT ON tblPROJECT.id = tblCAPACITY_PROJECT.fk_project_id
INNER JOIN tblCOMPANY ON tblCOMPANY.id = tblPROJECT.fk_company_id
INNER JOIN tblLOCATION ON tblPROJECT.fk_location_id = tblLOCATION.id
INNER JOIN vwCOMMANDERS ON tblPROJECT.fk_commander_id = vwCOMMANDERS.id
INNER JOIN tblPROJECT_COMPANY_DEPARTMENT ON tblPROJECT.id = tblPROJECT_COMPANY_DEPARTMENT.fk_project_id
INNER JOIN tblCOMPANY_DEPARTMENT ON tblPROJECT_COMPANY_DEPARTMENT.fk_company_department_id = tblCOMPANY_DEPARTMENT.id
INNER JOIN tblCOMPANY_STRUCTURE ON tblCOMPANY_DEPARTMENT.id = tblCOMPANY_STRUCTURE.fk_company_department_id
AND tblCOMPANY_STRUCTURE.[year] = 2014
INNER JOIN tblCOMPANY_BUSINESSUNIT ON tblCOMPANY_STRUCTURE.fk_company_businessunit_id = tblCOMPANY_BUSINESSUNIT.id
INNER JOIN (
SELECT ISNULL(SUM(employeesweek),0) * 40 Total, PCD1.fk_company_department_id
FROM tblPROJECT as P1
INNER JOIN tblPROJECT_COMPANY_DEPARTMENT as PCD1 on P1.id = PCD1.fk_project_id
AND PCD1.fk_company_structure_instance_id = 38
AND P1.active = 1 AND P1.capacityproject = 1
AND P1.status = 'D' AND PCD1.fk_company_department_id = 956
LEFT OUTER JOIN tblCAPACITY_PROJECT as CP1 ON CP1.fk_project_id = P1.id
AND CAST(CP1.Year AS Varchar(4)) + CP1.weeknumber BETWEEN 201425 AND 201436
GROUP BY PCD1.fk_company_department_id
) sTotal
ON sTotal.fk_company_department_id = tblPROJECT_COMPANY_DEPARTMENT.fk_company_department_id
INNER JOIN (
SELECT ISNULL(SUM(employeesweek),0) Week1, PCD1.fk_company_department_id
FROM tblPROJECT as P1 INNER JOIN tblPROJECT_COMPANY_DEPARTMENT as PCD1 on P1.id = PCD1.fk_project_id
AND PCD1.fk_company_structure_instance_id = 38
AND P1.active = 1 AND P1.capacityproject = 1
AND P1.status = 'D' AND PCD1.fk_company_department_id = 956
LEFT OUTER JOIN tblCAPACITY_PROJECT as CP1 ON CP1.fk_project_id = P1.id
AND CP1.Year = 2014 AND CP1.Weeknumber = 25
GROUP BY PCD1.fk_company_department_id
) sWeek1
ON sWeek1.fk_company_department_id = tblPROJECT_COMPANY_DEPARTMENT.fk_company_department_id
INNER JOIN (
SELECT ISNULL(SUM(employeesweek),0) Week2,
...
) sWeek2
ON sWeek2.fk_company_department_id = tblPROJECT_COMPANY_DEPARTMENT.fk_company_department_id
INNER JOIN ( SELECT ISNULL(SUM(employeesweek),0) Week3,
...
) sWeek3
ON sWeek3.fk_company_department_id = tblPROJECT_COMPANY_DEPARTMENT.fk_company_department_id
INNER JOIN (
SELECT ROUND(ISNULL(SUM(employeesweek),0) / 4.0,2,0) Period1, PCD1.fk_company_department_id
FROM tblPROJECT as P1 INNER JOIN tblPROJECT_COMPANY_DEPARTMENT as PCD1 on P1.id = PCD1.fk_project_id
AND PCD1.fk_company_structure_instance_id = 38
AND P1.active = 1 AND P1.capacityproject = 1 AND P1.status = 'D' AND PCD1.fk_company_department_id = 956
LEFT OUTER JOIN tblCAPACITY_PROJECT as CP1 ON CP1.fk_project_id = P1.id
AND CP1.Year = 2014 AND CP1.period = 08
GROUP BY PCD1.fk_company_department_id
) sPeriod1
ON sPeriod1.fk_company_department_id = tblPROJECT_COMPANY_DEPARTMENT.fk_company_department_id
INNER JOIN ( SELECT ROUND(ISNULL(SUM(employeesweek),0) / 4.0,2,0) Period2
...
) sPeriod2
ON sPeriod2.fk_company_department_id = tblPROJECT_COMPANY_DEPARTMENT.fk_company_department_id
这看起来很有希望,但SQL客户端统计数据说不然...... 有没有人知道如何让它更快?
这是主表的创建:
CREATE TABLE [dbo].[tblCAPACITY_PROJECT](
[id] [int] IDENTITY(1,1) NOT NULL,
[fk_project_id] [int] NOT NULL,
[year] [int] NOT NULL,
[period] [char](2) NOT NULL,
[weeknumber] [char](2) NULL,
[employeesweek] [float] NULL,
[lastmodifyweek] [char](6) NULL,
[fk_functiongroup_id] [int] NOT NULL,
[lastmodifydate] [smalldatetime] NULL,
[logfield] [varchar](8000) NULL,
CONSTRAINT [PK_tblCAPACITY_PROJECT] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING ON
GO
ALTER TABLE [dbo].[tblCAPACITY_PROJECT] WITH CHECK ADD CONSTRAINT [FK_tblCAPACITY_PROJECT_tblFUNCTIONGROUP] FOREIGN KEY([fk_functiongroup_id])
REFERENCES [dbo].[tblFUNCTIONGROUP] ([id])
GO
ALTER TABLE [dbo].[tblCAPACITY_PROJECT] CHECK CONSTRAINT [FK_tblCAPACITY_PROJECT_tblFUNCTIONGROUP]
GO
ALTER TABLE [dbo].[tblCAPACITY_PROJECT] WITH NOCHECK ADD CONSTRAINT [FK_tblCAPACITY_PROJECT_tblPROJECT] FOREIGN KEY([fk_project_id])
REFERENCES [dbo].[tblPROJECT] ([id])
GO
ALTER TABLE [dbo].[tblCAPACITY_PROJECT] CHECK CONSTRAINT [FK_tblCAPACITY_PROJECT_tblPROJECT]
GO
对于索引:
CREATE NONCLUSTERED INDEX [_dta_index_project_year_period] ON [dbo].[tblCAPACITY_PROJECT]
(
[fk_project_id] ASC,
[year] ASC,
[period] ASC
)
CREATE NONCLUSTERED INDEX [_dta_index_project_year_period_func] ON [dbo].[tblCAPACITY_PROJECT]
(
[fk_project_id] ASC,
[year] ASC,
[period] ASC,
[fk_functiongroup_id] ASC
)
CREATE NONCLUSTERED INDEX [_dta_index_tblCAPACITY_PROJECT_project_id_weeknumber_year] ON [dbo].[tblCAPACITY_PROJECT]
(
[fk_project_id] ASC,
[id] ASC,
[weeknumber] ASC,
[year] ASC
)
INCLUDE ( [period],
[employeesweek],
[lastmodifyweek],
[fk_functiongroup_id],
[lastmodifydate],
[logfield])
CREATE NONCLUSTERED INDEX [_dta_index_tblCAPACITY_PROJECT_project_year_week] ON [dbo].[tblCAPACITY_PROJECT]
(
[fk_project_id] ASC,
[year] ASC,
[weeknumber] ASC
)
INCLUDE ( [employeesweek],
[lastmodifyweek])
CREATE NONCLUSTERED INDEX [_dta_index_tblCAPACITY_PROJECT_project_year_week_functiongroup] ON [dbo].[tblCAPACITY_PROJECT]
(
[fk_project_id] ASC,
[year] ASC,
[weeknumber] ASC,
[fk_functiongroup_id] ASC
)
INCLUDE ( [employeesweek],
[lastmodifyweek])
CREATE NONCLUSTERED INDEX [IX_fk_project_id] ON [dbo].[tblCAPACITY_PROJECT]
(
[fk_project_id] ASC
)
CREATE NONCLUSTERED INDEX [IX_tblCAPACITY_PROJECT_functiongroup] ON [dbo].[tblCAPACITY_PROJECT]
(
[fk_functiongroup_id] ASC
)
CREATE NONCLUSTERED INDEX [IX_tblCAPACITY_PROJECT_weeknumber] ON [dbo].[tblCAPACITY_PROJECT]
(
[weeknumber] ASC
)
CREATE NONCLUSTERED INDEX [IX_tblCAPACITY_PROJECT_year] ON [dbo].[tblCAPACITY_PROJECT]
(
[year] ASC
)
ALTER TABLE [dbo].[tblCAPACITY_PROJECT] ADD CONSTRAINT [PK_tblCAPACITY_PROJECT] PRIMARY KEY CLUSTERED
(
[id] ASC
)