3

金額フィールドを含む会計テーブルがあります。テーブルの他のフィールドのいくつかを使用して、その金額のペニーごとに1行を返すビューを作成したいと思います。

非常に簡単な例として、次のような行があるとします。

PK     Amount     Date
---------------------------
123    4.80       1/1/2012

クエリ/ビューは、すべて次のように見える480行(ペニーごとに1つ)を返す必要があります。

PK      Date
-----------------
123     1/1/2012

これを達成するための最もパフォーマンスの高い方法は何でしょうか?テーブル値関数と一時テーブルを使用するソリューションがありますが、頭の後ろでは、従来のビューでこれを実現する方法が必要だと考え続けています。おそらく、創造的なクロス結合、または一時テーブルやtbfなどの形式であまりにも多くのリソースを宣言することなくこの結果を返す何か。何かアイデアはありますか?

4

2 に答える 2

3

次のようなCTEを使用できます。

WITH duplicationCTE AS 
(
    SELECT PK, Date, Amount, 1 AS Count
    FROM myTable
    UNION ALL
    SELECT myTable.PK, myTable.Date, myTable.Amount, Count+1
    FROM myTable
         JOIN duplicationCTE ON myTable.PK = duplicationCTE.PK
    WHERE Count+1 <= myTable.Amount*100
)
SELECT PK, Date
FROM duplicationCTE
OPTION (MAXRECURSION 0);

これがSqlFiddleです

また、0に注意してください。これは、これが無限に実行される可能性があることを意味します(危険です)。それ以外の場合、32676は、設定できる再帰の最大数です(デフォルトは100)。ただし、32676ループを超えて実行している場合は、ロジックを再考する必要があるかもしれません:)

于 2012-04-13T18:12:32.763 に答える
3

数字の表を少し使用すると、次のように実行できます。

select PK, [Date]
from YourTable as T
  inner join number as N
    on N.n between 1 and T.Amount * 100 

周りに1つがなく、これをテストしたい場合は、master..spt_valuesを使用できます。

declare @T table
(
  PK int,
  Amount money,
  [Date] date
)

insert into @T values
(123,    4.80,       '20120101')


;with number(n) as
(
  select number 
  from master..spt_values
  where type = 'P'
)
select PK, [Date]
from @T as T
  inner join number as N
    on N.n between 1 and T.Amount * 100 

更新:
JeffModenによる記事から。
「数値」または「集計」テーブル:それが何であるか、そしてそれがループをどのように置き換えるか。

Tallyテーブルは、0または1(私の場合は1から始まり)からいくつかの番号までの非常に適切にインデックス付けされた連続番号の単一列を持つテーブルにすぎません。タリーテーブルの最大数は、単なる任意の選択ではありません。それはあなたがそれを使うと思うものに基づいているべきです。VARCHAR(8000)を自分のものと分割したので、少なくとも8000個の数値である必要があります。30年の日付を生成する必要がある場合があるため、本番のTallyテーブルのほとんどを11,000以上に保ちます。これは、365。25日×30年を超えています。

于 2012-04-13T18:18:35.133 に答える