在搜索了其他答案以查看是否已经提出了这个特定问题(并且已经提出了其他口味 - 只是没有涵盖我需要询问的所有内容)之后,我想提出以下场景并就最常见的问题寻求建议创建此报告查询的有效方法。这是一篇冗长的帖子,不幸的是,我不允许发布任何 T-SQL 代码——我的雇主明确禁止这样做。
这些年来我学到的一件事是,有很多人比我知道的多得多——所以在搜索并没有找到你需要的东西之后,问问别人吧:)
所有表都有主键,如果有链接到子表的表,则有外键。数据库和报表服务器是 SQL 2008 R2。该服务器运行 128GB RAM,是一个 4CPU 四核超线程野兽。
首先,我有一组包含 Locations、Sections 和 Areas 的表。位置通过映射表链接到部分 - 部分有多个位置,部分通过映射表链接到区域,并且有多个部分到区域。这些表都位于数据库“A”中。我在一个单独的数据库“B”中创建了一个视图,它代表了一个快速执行的漂亮结果集中的区域 - 部分 - 位置链接。我称之为 LocationSectionArea 视图。
在数据库“B”中,成千上万的用户正在输入他们关于他们工作的各种类别的日常统计数据。目前有91个类别。每个类别将包含从大约 3 个到多达 25 个不等的子类别。类别和子类别的数量可以随时更改,通过管理界面添加或删除更多。我创建了一个视图来表示这些链接并返回一个名为 CategorySubCategoryFields 视图的结果集。
为每个类别/子类别链接收集的信息各不相同 - 有些需要大约 8 个不同的字段,有些需要 3 个,有些只需要 1 个。这些字段链接到相应的子类别。这再次包含在数据库“B”中。
我已经构建了一个视图,可以很好地将这些数据放在这个数据库中,最终得到一个大的结果矩阵,以一种可以很容易报告的方式呈现数据,并且到目前为止的视图执行似乎是完全可以接受的速度。我称之为 UserStatsView。这包含在数据库“B”中。
现在 - 输入数据的用户被分配到前面提到的位置之一。结果需要显示一个部分内的所有位置,一个区域内的所有部分,以及每个位置显示该类别的每个类别和子类别。然后需要将其链接到来自 UserStatsView 的结果,因此您最终会得到一个相当大的这些结果矩阵,其中混杂着许多没有结果的 0 - 但它们是为报告目的而创建的。
报告必须允许用户,例如,选择一个部分,然后生成该部分中包含的所有位置的报告,以及用户为该位置输入的结果的统计 - 对于每个类别-子类别组合有。无论用户是否输入了实际结果,它都必须显示该部分的所有位置和所有类别-子类别。因此,某些报告上可能有很多 0。
为此,我创建了一个将 LocationSectionArea 与 CategorySubCategoryFields 视图交叉连接的结果视图。这创建了我想要的基本矩阵。然后我将这个矩阵加入到 UserStatsView 的结果中,加入 LocationId、CategoryId 和 SubCategoryId 以插入位置的用户结果。这都是在数据库“B”中创建的。
现在,如果您在最后的 where 子句中提供足够的过滤器以减少记录数量,这一切都可以正常工作并且“可以”。正如您所想象的那样 - 如果他们尝试运行具有更大结果集的报告 - 它开始变得非常缓慢。(即,涵盖所有地点 6 个月的日期范围需要超过 30 秒)
我的部分问题是我相信位置信息是从数据库“A”链接进来的,并且构造的视图包含在数据库“B”中,以及该报告所需的所有其他信息的所有视图表和记录。
另一部分是我相信创建的非常大和复杂的交叉连接然后链接到用户结果的视图。交叉连接是在与 UserStatsView 结果集连接之前没有索引或相关数据的笛卡尔结果。
我认为的第三个问题是,正在“创建”数据以填补所有空白,以便生成可以输入 SSRS 的结果结构。我已经看到表假脱机和散列连接占用了大量执行时间,以及从数据库中查找位置、部分和区域。这些都通过查询执行估计计划显示出来。
我要问的是,根据上述标准,是否有人知道是否有更好的方法来生成此结果集。我是否完全错过了一种非常简单快捷的方法,这很有可能:)。如果有人可以建议我应该研究什么,我会很乐意去做——只是不确定现阶段要研究什么?
干杯
杆。
更新:以下是定义两个数据库的表结构,。显然,真正的桌子还有更多,但这是它们如何挂在一起的关键。请原谅这么大的帖子 - 我已经删除了除了关键字段和一些数据字段之外的所有内容,以便您查看表格的结构。表名和字段名已更改为通用名称,删除了许多额外字段,因此我可以发布代码。
数据库 A
**Location Table**
LocationId BIGINT PK
LocationName Varchar(100)
**Section Table**
SectionId Bigint PK
SectionName varchar(100)
**Area Table**
AreaId Bigint PK
AreaName varchar(100)
**LocationSectionMap Table**
LocSecId Bigint PK
LocationId Bigint FK Index to Location Table
SectionId BigInt FK Index to Section Table
**SectionAreaMap Table**
SecAreaId Bigint PK
SectionId Bigint FK Index to Section Table
AreaId Bigint FK Index to Area Table
数据库 B
**Categories Table**
CategoryId Bigint PK
categoryName varchar(100)
**SubCategories Table**
SubCategoryId Bigint
CategoryId Bigint FK to Categories Table
SubCategoryType Int
FieldTypeId Int (1, 2, 3 or 4)
**UserStats Table**
UserStatId bigint PK
UserId Bigint
StartDate DateTime
EndDate DateTime
LocationId Bigint --> this is the location ID in Location table in database A
SectionId Bigint --> this is the Section ID in Section Table in database A
AreaId Bigint --> this is the Area ID of the Area Table in database A
**FieldType1 Table**
FieldType1Id bigint PK
UserStatId Bigint FK to UserStats Table
SubCategoryId Bigint FK to Subcategories Table
Value1 int
Value2 int
**FieldType2 Table**
FieldType2Id bigint PK
UserStatId Bigint FK to UserStats Table
SubCategoryId Bigint FK to Subcategories Table
Value1 int
Value2 int
Value4 int
Value5 int
Value6 int
Value7 int
Value8 int
Value9 int
Value10 int
**FieldType3 Table**
FieldType3Id bigint PK
UserStatId Bigint FK to UserStats Table
SubCategoryId Bigint FK to Subcategories Table
Value1 int
Value2 int
Value11 int
Value12 int
Value13 int
Value14 int
Value15 int
Value16 int
**FieldType4 Table**
FieldType4Id bigint PK
UserStatId Bigint FK to UserStats Table
SubCategoryId Bigint FK to Subcategories Table
CombinedValue1And2 int
**SubCategoryAssociations Table**
SubCategoryAssociationId Int PK
ReportOfSubCategoryId bigint FK to Subcategories Table
IncludeValuesFromSubcategoryId Bigint FK to Subcategories Table
视图:数据库 A 中的区域-截面-位置视图 (vwAreasSectionsAndLocations)
SELECT A.AreaId, A.AreaName, C.SectionId, C.SectionName, E.LocationId, E.LocationName
FROM DatabaseA.dbo.tblAreas AS A INNER JOIN
DatabaseA.dbo.tblAreaSections AS B ON A.AreaId = B.AreaId INNER JOIN
DatabaseA.dbo.tblSections AS C ON B.SectionId = C.SectionId INNER JOIN
DatabaseA.dbo.tblSectionLocations AS D ON C.SectionId = D.SectionId INNER JOIN
DatabaseA.dbo.tblLocations AS E ON D.LocationId = E.LocationId
数据库 B 中的 Category-SubCategory 视图 (vwCategoryAndSubCategory)
SELECT TOP (100) PERCENT dbo.tblCategories.CategoryId,
dbo.tblCategories.CategoryName,
dbo.tblSubCategory.SubCategoryId,
dbo.tblSubCategory.SubCategoryname,
dbo.tblSubCategory.SubCategoryTypeId
FROM dbo.tblCategories INNER JOIN
dbo.tblSubCategory ON dbo.tblCategories.CategoryId = dbo.tblSubCategory.CategoryId
ORDER BY dbo.tblCategories.CategoryName, dbo.tblSubCategory.SubCategoryname
视图交叉连接两个视图以创建所需的结果矩阵(无结果)(vwAreaSectionLocationCategorySubCategory)
SELECT dbo.vwCategoryAndSubCategory.CategoryId, dbo.vwCategoryAndSubCategory.CategoryName,
dbo.vwCategoryAndSubCategory.CategoryPlacementOrder, dbo.vwCategoryAndSubCategory.IsStandardDaybookEntryCategory,
dbo.vwCategoryAndSubCategory.SubCategoryId, dbo.vwCategoryAndSubCategory.SubCategoryname, dbo.vwCategoryAndSubCategory.SubCategoryTypeId,
dbo.vwCategoryAndSubCategory.SubCategoryPlacementOrder, dbo.vwAreasSectionsAndLocations.AreaId, dbo.vwAreasSectionsAndLocations.AreaName,
dbo.vwAreasSectionsAndLocations.SectionId, dbo.vwAreasSectionsAndLocations.SectionName, dbo.vwAreasSectionsAndLocations.LocationId,
dbo.vwAreasSectionsAndLocations.LocationName
FROM dbo.vwCategoryAndSubCategory CROSS JOIN
dbo.vwAreasSectionsAndLocations
创建使用统计结果的视图 (vwUserStatsResults)
SELECT dbo.tblUserStats.UserStatId,
dbo.tblUserStats.UserId,
dbo.tblUserStats.LocationId,
dbo.tblUserStats.SectionId,
dbo.tblUserStats.AreaId,
dbo.tblUserStats.StartDate,
dbo.tblUserStats.EndDate,
dbo.tblFieldType1.CategoryId,
dbo.tblFieldType1.SubCategoryId,
1 AS FieldTypeId,
(dbo.tblFieldType1.Value1 + ISNULL
((SELECT SUM(A.Value1)
FROM dbo.tblFieldType1 A
WHERE A.SubCategoryId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE ReportOnSubCategoryId = A.SubCategoryId) AND dbo.tblFieldType1.UserStatId = A.UserStatId), 0)
+ ISNULL
((SELECT SUM(A.Value1)
FROM dbo.tblFieldType2 A
WHERE A.SubCategoryId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE ReportOnSubCategoryId = A.SubCategoryId) AND dbo.tblFieldType1.UserStatId = A.UserStatId), 0)
+ ISNULL
((SELECT SUM(A.Value1)
FROM dbo.tblFieldType3 A
WHERE A.SubCategoryId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE ReportOnSubCategoryId = A.SubCategoryId) AND dbo.tblFieldType1.UserStatId = A.UserStatId), 0))
AS Value1, (dbo.tblFieldType1.Value2 + ISNULL
((SELECT SUM(A.Value2)
FROM dbo.tblFieldType1 A
WHERE A.SubCategoryId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE ReportOnSubCategoryId = A.SubCategoryId) AND dbo.tblFieldType1.UserStatId = A.UserStatId), 0)
+ ISNULL
((SELECT SUM(A.Value2)
FROM dbo.tblFieldType2 A
WHERE A.SubCategoryId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE ReportOnSubCategoryId = A.SubCategoryId) AND dbo.tblFieldType1.UserStatId = A.UserStatId), 0)
+ ISNULL
((SELECT SUM(A.Value2)
FROM dbo.tblFieldType3 A
WHERE A.SubCategoryId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE ReportOnSubCategoryId = A.SubCategoryId) AND dbo.tblFieldType1.UserStatId = A.UserStatId), 0))
AS Value2, Value1 + Value2 AS CombinedValue1And2, 0 AS Value3, 0 AS Value4,
0 AS Value5, 0 AS Value6, 0 AS Value7, 0 AS Value8,
0 AS Value9, 0 AS Value10, 0 AS Value11, 0 AS Value12, 0 AS Value13,
0 AS Value14, 0 AS Value15, 0 AS Value16
FROM dbo.tblUserStats INNER JOIN
dbo.tblFieldType1 ON dbo.tblUserStats.UserStatId = dbo.tblFieldType1.UserStatId
UNION ALL
SELECT dbo.tblUserStats.UserStatId,
dbo.tblUserStats.UserId,
dbo.tblUserStats.LocationId,
dbo.tblUserStats.SectionId,
dbo.tblUserStats.AreaId,
dbo.tblUserStats.StartDate,
dbo.tblUserStats.EndDate,
dbo.tblFieldType2.CategoryId,
dbo.tblFieldType2.SubCategoryId,
2 AS FieldTypeId,
dbo.tblFieldType2.Value1 + ISNULL
((SELECT SUM(Value1) AS Expr1
FROM dbo.tblFieldType1 AS A
WHERE (FieldId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE (ReportOnSubCategoryId = A.SubCategoryId))) AND (dbo.tblFieldType2.UserStatId = UserStatId)), 0)
+ ISNULL
((SELECT SUM(Value1) AS Expr1
FROM dbo.tblFieldType2 AS A
WHERE (FieldId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE (ReportOnSubCategoryId = A.SubCategoryId))) AND (dbo.tblFieldType2.UserStatId = UserStatId)), 0)
+ ISNULL
((SELECT SUM(Value1) AS Expr1
FROM dbo.tblFieldType3 AS A
WHERE (FieldId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE (ReportOnSubCategoryId = A.SubCategoryId))) AND (dbo.tblFieldType2.UserStatId = UserStatId)), 0)
AS Value1, dbo.tblFieldType2.Value2 + ISNULL
((SELECT SUM(Value2) AS Expr1
FROM dbo.tblFieldType1 AS A
WHERE (FieldId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE (ReportOnSubCategoryId = A.SubCategoryId))) AND (dbo.tblFieldType2.UserStatId = UserStatId)), 0)
+ ISNULL
((SELECT SUM(Value2) AS Expr1
FROM dbo.tblFieldType2 AS A
WHERE (FieldId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE (ReportOnSubCategoryId = A.SubCategoryId))) AND (dbo.tblFieldType2.UserStatId = UserStatId)), 0)
+ ISNULL
((SELECT SUM(Value2) AS Expr1
FROM dbo.tblFieldType3 AS A
WHERE (FieldId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE (ReportOnSubCategoryId = A.SubCategoryId))) AND (dbo.tblFieldType2.UserStatId = UserStatId)), 0)
AS Value2, dbo.tblFieldType2.Value1 + dbo.tblFieldType2.Value2 AS CombinedValue1And2,
ISNULL(dbo.tblFieldType2.Value3, 0), ISNULL(dbo.tblFieldType2.Value4, 0),
ISNULL(dbo.tblFieldType2.Value5, 0), ISNULL(dbo.tblFieldType2.Value6, 0),
ISNULL(dbo.tblFieldType2.Value7, 0), ISNULL(dbo.tblFieldType2.Value8, 0),
ISNULL(dbo.tblFieldType2.Value9, 0), ISNULL(dbo.tblFieldType2.Value10, 0),
0 AS Value11, 0 AS Value12, 0 AS Value13, 0 AS Value14, 0 AS Value15,
0 AS Value16
FROM dbo.tblUserStats INNER JOIN
dbo.tblFieldType2 ON dbo.tblUserStats.UserStatId = dbo.tblFieldType2.UserStatId
UNION ALL
SELECT dbo.tblUserStats.UserStatId,
dbo.tblUserStats.UserId,
dbo.tblUserStats.LocationId,
dbo.tblUserStats.SectionId,
dbo.tblUserStats.AreaId,
dbo.tblUserStats.StartDate,
dbo.tblUserStats.EndDate,
dbo.tblFieldType3.CategoryId,
dbo.tblFieldType3.SubCategoryId,
3 AS FieldTypeId,
dbo.tblFieldType3.Value1 + ISNULL
((SELECT SUM(Value1) AS Expr1
FROM dbo.tblFieldType1 AS A
WHERE (FieldId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE (ReportOnSubCategoryId = A.SubCategoryId))) AND (dbo.tblFieldType3.UserStatId = UserStatId)), 0)
+ ISNULL
((SELECT SUM(Value1) AS Expr1
FROM dbo.tblFieldType2 AS A
WHERE (FieldId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE (ReportOnSubCategoryId = A.SubCategoryId))) AND (dbo.tblFieldType3.UserStatId = UserStatId)), 0)
+ ISNULL
((SELECT SUM(Value1) AS Expr1
FROM dbo.tblFieldType3 AS A
WHERE (FieldId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE (ReportOnSubCategoryId = A.SubCategoryId))) AND (dbo.tblFieldType3.UserStatId = UserStatId)), 0)
AS Value1, dbo.tblFieldType3.Value2 + ISNULL
((SELECT SUM(Value2) AS Expr1
FROM dbo.tblFieldType1 AS A
WHERE (FieldId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE (ReportOnSubCategoryId = A.SubCategoryId))) AND (dbo.tblFieldType3.UserStatId = UserStatId)), 0)
+ ISNULL
((SELECT SUM(Value2) AS Expr1
FROM dbo.tblFieldType2 AS A
WHERE (FieldId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE (ReportOnSubCategoryId = A.SubCategoryId))) AND (dbo.tblFieldType3.UserStatId = UserStatId)), 0)
+ ISNULL
((SELECT SUM(Value2) AS Expr1
FROM dbo.tblFieldType3 AS A
WHERE (FieldId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE (ReportOnSubCategoryId = A.SubCategoryId))) AND (dbo.tblFieldType3.UserStatId = UserStatId)), 0)
AS Value2, dbo.tblFieldType3.Value1 + dbo.tblFieldType3.Value2 AS CombinedValue1And2, 0 AS Value3,
0 AS Value4, 0 AS Value5, 0 AS Value6, 0 AS Value7,
0 AS Value8, 0 AS Value9, 0 AS Value10,
ISNULL(dbo.tblFieldType3.Value11, 0), ISNULL(dbo.tblFieldType3.Value12, 0),
ISNULL(dbo.tblFieldType3.Value13, 0), ISNULL(dbo.tblFieldType3.Value14, 0),
ISNULL(dbo.tblFieldType3.Value15, 0), ISNULL(dbo.tblFieldType3.Value16, 0)
FROM dbo.tblUserStats INNER JOIN
dbo.tblFieldType3 ON dbo.tblUserStats.UserStatId = dbo.tblFieldType3.UserStatId
UNION ALL
SELECT dbo.tblUserStats.UserStatId,
dbo.tblUserStats.UserId,
dbo.tblUserStats.LocationId,
dbo.tblUserStats.SectionId,
dbo.tblUserStats.AreaId,
dbo.tblUserStats.StartDate,
dbo.tblUserStats.EndDate,
dbo.tblFieldType4.CategoryId,
dbo.tblFieldType4.SubCategoryId,
4 AS FieldTypeId,
0 AS Value1, 0 AS Value2, dbo.tblFieldType4.CombinedValue1And2 + (ISNULL
((SELECT SUM(A.Value1)
FROM dbo.tblFieldType1 A
WHERE A.SubCategoryId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE ReportOnSubCategoryId = A.SubCategoryId) AND dbo.tblFieldType4.UserStatId = A.UserStatId), 0)
+ ISNULL
((SELECT SUM(A.Value1)
FROM dbo.tblFieldType2 A
WHERE A.SubCategoryId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE ReportOnSubCategoryId = A.SubCategoryId) AND dbo.tblFieldType4.UserStatId = A.UserStatId), 0)
+ ISNULL
((SELECT SUM(A.Value1)
FROM dbo.tblFieldType3 A
WHERE A.SubCategoryId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE ReportOnSubCategoryId = A.SubCategoryId) AND dbo.tblFieldType4.UserStatId = A.UserStatId), 0))
+ (ISNULL
((SELECT SUM(A.Value2)
FROM dbo.tblFieldType1 A
WHERE A.SubCategoryId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE ReportOnSubCategoryId = A.SubCategoryId) AND dbo.tblFieldType4.UserStatId = A.UserStatId), 0)
+ ISNULL
((SELECT SUM(A.Value2)
FROM dbo.tblFieldType2 A
WHERE A.SubCategoryId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE ReportOnSubCategoryId = A.SubCategoryId) AND dbo.tblFieldType4.UserStatId = A.UserStatId), 0)
+ ISNULL
((SELECT SUM(A.Value2)
FROM dbo.tblFieldType3 A
WHERE A.SubCategoryId IN
(SELECT DISTINCT IncludeValuesFromSubCategoryId
FROM dbo.tblSubCategoryAssociations
WHERE ReportOnSubCategoryId = A.SubCategoryId) AND dbo.tblFieldType4.UserStatId = A.UserStatId), 0))
AS CombinedValue1And2, 0 AS Value3, 0 AS Value4, 0 AS Value5, 0 AS Value6,
0 AS Value7, 0 AS Value8, 0 AS Value9, 0 AS Value10,
0 AS Value11, 0 AS Value12, 0 AS Value13, 0 AS Value14, 0 AS Value15,
0 AS Value16
FROM dbo.tblUserStats INNER JOIN
dbo.tblFieldType4 ON dbo.tblUserStats.UserStatId = dbo.tblFieldType4.UserStatId
最后是把所有东西放在一起的视图 (vwReportResults)
由于字数限制,在另一个条目中发表