3

SQL(MS 2008 r2)2の比較的単純なテーブルを合計すると、それを機能させる方法を見つけるのに苦労していますが、SQLの専門家の助けを借りてください:)

ツリータイプのテーブルを値のコレクションに結合します。ここでは、値の最新のインスタンス(外部キーx2ごと)のみを取得し、各値には作成日があり、作成日までに最新の値のみが必要です。また、最後に、ツリーの最下部にある値(つまり、子のない値)のみを合計したいと思います。私はCTEについて読み、これを機能させるための良い方法だと思いましたが、これまでにこれを行ったことがないので、私が書いたものを読むのに少し苦労しています:)

ノードと呼ばれる比較的単純なツリーテーブルがあります

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

私が興味を持っているこの表のデータは次のようなものです。(実際の単純な例では、最大で7レベルのネストの1000〜2000レコード、通常は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

ツリーに参加するのはcrewIdであり、これはパラメーターとして送信されるため、たとえば1077のすべての子の合計を取得します。子のない値の合計のみを含めたいと思います。私はmealIdの各値の合計が必要です。クルーID+ミールID+作成は常に一意です。

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 に答える