0

2つのテーブルがTblValありTblAdjます。

には、与えられた値に応じて調整し、いくつかの値を返すTblVal必要のある値がたくさんあります。これらの調整のみを適用する必要があります。TblAdjTblVal.PersonIDTblVal.DateViewAdjustedValuesTblAdj.Date >= TblVal.Date

問題は、すべての調整が減算または除算のいずれかであるため、順番に行う必要があることです。テーブルの構造は次のとおりです。

TblVal::PersonID, Date, Value
TblAdj_PersonID, Date, SubtractAmount, DivideAmount

戻りたいViewAdjustedValuesPersonID, Date, AdjValue

ループとブロックをTblAdj使用して、必要に応じて減算または除算を繰り返すことなく、これを実行できますか?より速く実行できるネストされたSELECTテーブルの魔法はありますか?WHILEIF

4

2 に答える 2

0

次のようなものを試してください。


with CTE_TblVal (PersonID,Date,Value)
as 
(
   select A.PersonID, A.Date, A.Value 
   from TblVal A
   inner join TblAdj B
   on A.PersonID = B.PersonID
   where B.Date >= A.Date
)
update CTE_TblVal
set Date = TblAdj.Date,
    Value = TblAdj.Value
from CTE_TblVal
   inner join TblAdj 
   on CTE_Tblval.PersonID = TblAdj.PersonID
output inserted.* into ViewAdjustedValues
select * from ViewAdjustedValues 
于 2013-03-25T23:42:07.767 に答える
0

ループなしでもできると思いますが、やりたいかどうかは別問題です。私がうまくいくと思うクエリは以下のとおりです(SQL Fiddleはこちら)。主なアイデアは次のとおりです。

各SubtractAmountには、SubtractAmountを、同じPersonIDの後続のすべてのDivideAmountの積で割った値を差し引くという最終的な効果があります。PersonIDに関連付けられている日付は、この調整には関係ありません(幸いなことに)。CTE AdjustedAdjustmentsには、これらの調整されたSubtractAmount値が含まれています。

PersonIDの初期値は、その人物の日付以降のすべてのDivideAmount値の積で除算されます。

EXP(SUM(LOG(x)))は、xのすべての値が正の場合、集計積として機能します。これを保証するためにDivideAmount値を制約するか、それに応じてコードを調整する必要があります。

DivideAmountsがない場合、関連する積はNULLであり、1に変更されます。同様に、調整されたSubtractAmount値のNULL合計はゼロに変更されます。左結合は、調整の対象とならない値を保持するために使用されます。

SQL Server 2012は、集計のOVER句をサポートしています。これは、ここで「以降のすべてのDivideAmounts」を集計するのに役立ちました。

WITH AdjustedAdjustments AS (

select
  PersonID,
  Date,
  SubtractAmount/
  EXP(
    SUM(LOG(COALESCE(DivideAmount,1)))
      OVER (
        PARTITION BY PersonID
        ORDER BY Date
        ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
      )
  ) AS AdjustedSubtract,
  DivideAmount
  FROM TblAdj
)

  SELECT
    p.PersonID,
    p.Value/COALESCE(EXP(SUM(LOG(COALESCE(DivideAmount,1)))),1)
      -COALESCE(SUM(a.AdjustedSubtract),0) AS AmountAdjusted
  FROM TblVal AS p
  LEFT OUTER JOIN AdjustedAdjustments AS a
  ON a.PersonID = p.PersonID
  AND a.Date >= p.Date
  GROUP BY p.PersonID, p.Value, p.Date;
于 2013-03-26T00:31:18.970 に答える