3

想要总结 SQL (MS 2008 r2) 2 个相对简单的表,我正在努力寻找一种让它工作的方法,几乎​​就在那里,但我真的很感谢 SQL 专家的帮助:)

我将一个树型表加入到一组值中,我们只检索该值的最新实例(对于每个外键 x2),并且每个值都有一个创建日期,我们只想要创建日期之前的最新值。最后,我们只想对位于树底部的那些(即没有孩子的)的值求和。我读过关于 CTE 的文章,并认为这是使它工作的好方法,但以前没有这样做过,所以仍然在努力阅读我所写的内容 :)

我有一个相对简单的树表,称为节点

[id] [int] IDENTITY(1,1) NOT NULL,
[parentID] [int] NOT NULL

我感兴趣的这张表中的数据是这样的。(实际的简单示例可能有 1000-2000 条记录,最多可能有 7 层嵌套,通常只有 3 或 4 层)ID + ParentID 始终是唯一的。

ID      parentID
1077    1055
1110    1077
1103    1077
1104    1103
1105    1103
1111    1110
1112    1110

然后是我想加入的另一个表分配。

[Id] [int] IDENTITY(1,1) NOT NULL,
[creation] [datetime] NULL,
[crewId] [int] NULL,
[mealId] [int] NULL,
[allocation] [int] NULL

加入树的是 crampId,这是作为参数发送的,因此我们将检索 1077 的所有孩子的总和。我只想包括无子值的总和。我想为 mealId 的每个值求一个总和。crampId + mealId + creation 始终是唯一的。

Id          creation                crewId      mealId      allocation
----------- ----------------------- ----------- ----------- -----------
1           2012-04-13 16:50:00.000 1111        1085        1
2           2012-04-13 16:55:00.000 1111        1085        3
3           2012-04-13 17:03:31.100 1111        1085        2
4           2012-04-18 22:35:21.790 1112        1085        1
5           2012-04-18 22:35:32.630 1112        1086        1
6           2012-04-18 22:35:42.473 1112        1087        1
7           2012-04-25 18:15:53.117 1111        1086        1
8           2012-04-25 19:11:46.227 1111        1085        1
9           2012-04-25 19:11:46.227 1110        1085        5

这是我目前所拥有的

declare  @crewId int
set @crewId = 1077

-- get total of allocated to childless children
;with 
Recurse as (
select 
  n.Id as DirectChildId
, n.Id
from umbracoNode n
where parentId = @crewId
union all
select
  b.DirectChildId
, n.Id
from umbracoNode n 
join Recurse b on b.Id = n.ParentId
)

select
  n.DirectChildId, mealId, sum(a.Allocation) as TotalAllocation
from Recurse n
left join Allocations a on n.Id = a.crewId
   and a.CrewId not in (select parentId from umbracoNode)
group by DirectChildId, mealId;

这几乎可行,但尚未考虑获取最新值。

我目前检索最新版本的查询如下所示。但我不知道如何将它们结合起来。

SELECT a.mealId, a.allocation
FROM Allocations AS a
  LEFT OUTER JOIN Allocations AS a2
  ON (a2.crewId = @crewId and a.MealId = a2.MealId AND a2.creation < a2.creation)
WHERE a.crewId = @crewId and a2.crewId IS NULL;
4

1 回答 1

0

我得到了这个工作,这是我的答案:

ALTER PROCEDURE [dbo].[tegsGetTotalAllocated] 
(@crewId As Integer)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
;with q as (
SELECT n.id
FROM umbracoNode n
WHERE n.id = @crewId
UNION ALL
   SELECT n2.id
    FROM  umbracoNode n2
    JOIN q 
    ON n2.parentId = q.id
)

SELECT
  sum(a.allocation) as totalAllocated, a.mealId
FROM q
left join Allocation_Meal a on q.Id = a.crewId
   and a.CrewId not in (select parentId from umbracoNode)
where mealId is not null 
group by mealId
END

主要技巧是创建一个执行最新部分的视图。我不太清楚这有什么影响。除了给我一种总是包含最新结果的虚拟表。这总是在每次点击时评估还是比这更聪明?

CREATE VIEW [dbo].[Allocation_Meal]
AS
SELECT t1.mealId, t1.allocation, t1.crewId
FROM tegsAllocation AS t1
      LEFT OUTER JOIN tegsAllocation AS t2
    ON (t2.crewId = t1.crewId and t1.MealId = t2.MealId AND t1.creation < t2.creation)
WHERE t2.crewId IS NULL;

非常感谢任何关于它是否可以更有效的想法或评论:)尤其是我应该添加哪些索引以使其更好地工作,或者是识别这些的好方法:)

于 2012-04-26T17:36:42.627 回答