2016-10-11 3 views
0

テーブルの情報に基づいて、テーブルに動的な行数を挿入したいとします。表の値を使用して動的な行数を表に挿入できますか?

私は以下のコードを使用してそれを行うことができますが、ループを回避する方法があるかどうかは疑問です。

コメントアウトされたセクションは、私がしようとしていたときの私の最高の試みでしたが、それは私にエラーをもたらしました: "TOPへの引数、" OFFSET " FETCH句。外部スコープの列への参照のみ、またはスタンドアロンの式とサブクエリはここで許可されます。

DECLARE @TableX TABLE (
     TDate   DATE 
    , TType   INT 
    , Fruit   NVARCHAR(20) 
    , Vegetable  NVARCHAR(20) 
    , Meat   NVARCHAR(20) 
    , Bread   NVARCHAR(20) 
    ) 

INSERT INTO @TableX VALUES 
     ('2016-11-10',1,'Apple','Artichoke',NULL,NULL) 
    , ('2016-11-10',1,'Banana','Beet',NULL,NULL) 
    , ('2016-11-10',1,'Canteloupe','Cauliflower',NULL,NULL) 
    , ('2016-11-10',1,'Durian','Daikon',NULL,NULL) 
    , ('2016-11-10',2,NULL,NULL,'Rabbit','Rye') 
    , ('2016-11-10',2,NULL,NULL,'Sausage','Sourdough') 
    , ('2016-11-11',1,'Elderberry','Eggplant',NULL,NULL) 
    , ('2016-11-11',2,NULL,NULL,'Turkey','Tortilla') 
    , ('2016-11-11',2,NULL,NULL,'Venison','Vienna') 

SELECT * FROM @TableX 

DECLARE @BlankRow TABLE (
     ID   INT IDENTITY 
    , TDate   DATE 
    , TType   INT 
    , iCount  INT 
    ) 

DECLARE @Counter1 INT = 0 
     , @RowCount INT 

; WITH BR1 
    AS (
     SELECT TDate, TType, COUNT(*) AS iCount 
      FROM @TableX 
       WHERE TType = 1 
        GROUP BY TDate, TType 
     ) 

, BR2 
    AS (
     SELECT TDate, TType, COUNT(*) AS iCount 
      FROM @TableX 
       WHERE TType = 2 
        GROUP BY TDate, TType 
     ) 

INSERT INTO @BlankRow 
    SELECT ISNULL(BR1.TDate, BR2.TDate) AS TDate, 
     CASE WHEN ISNULL(BR1.iCount,0) < ISNULL(BR2.iCount,0) THEN 1 ELSE 2 END AS TType, 
      ABS(ISNULL(BR1.iCount,0) - ISNULL(BR2.iCount,0)) AS iCount 
       FROM BR1 
        FULL JOIN BR2 
         ON BR1.TDate = BR2.TDate 

WHILE @Counter1 < (SELECT MAX(ID) FROM @BlankRow) 
    BEGIN 
     SET @Counter1 += 1 
     SET @RowCount = (SELECT iCount FROM @BlankRow WHERE ID = @Counter1) 
      INSERT INTO @TableX 
       SELECT TOP (@RowCount) tx.TDate, br.TType, NULL, NULL, NULL, NULL 
        FROM @TableX tx 
         LEFT JOIN @BlankRow br 
          ON tx.TDate = br.TDate 
         WHERE br.ID = @Counter1 
    END 

/*INSERT INTO @TableX 
SELECT TOP (tx.iCount) tx.TDate, br.TType, NULL, NULL, NULL, NULL 
     FROM @TableX tx 
      JOIN @BlankRow br 
       ON tx.TDate = br.TDate*/ 

SELECT * 
    FROM @TableX 
     ORDER BY TDate, TType, 
     ISNULL(Fruit,REPLICATE(CHAR(255),20)), 
     ISNULL(Vegetable,REPLICATE(CHAR(255),20)), 
     ISNULL(Meat,REPLICATE(CHAR(255),20)), 
     ISNULL(Bread,REPLICATE(CHAR(255),20)) 

データは、私が知っている、愚かですが、私の最終目標は、私のグループのヘッダは上の同じ場所に現れるように、同じ数の行で終わるReportBuilder 2つの異なるTablixの年代を持つことですページ。このような

答えて

1

何か:

declare @TableX table(TDate  date 
        ,TType  int 
        ,Fruit  nvarchar(20) 
        ,Vegetable nvarchar(20) 
        ,Meat  nvarchar(20) 
        ,Bread  nvarchar(20) 
        ); 

insert into @TableX values 
('2016-11-10',1,'Apple','Artichoke',NULL,NULL) 
,('2016-11-10',1,'Banana','Beet',NULL,NULL) 
,('2016-11-10',1,'Canteloupe','Cauliflower',NULL,NULL) 
,('2016-11-10',1,'Durian','Daikon',NULL,NULL) 
,('2016-11-10',2,NULL,NULL,'Rabbit','Rye') 
,('2016-11-10',2,NULL,NULL,'Sausage','Sourdough') 
,('2016-11-11',1,'Elderberry','Eggplant',NULL,NULL) 
,('2016-11-11',2,NULL,NULL,'Turkey','Tortilla') 
,('2016-11-11',2,NULL,NULL,'Venison','Vienna'); 


with DataRN as 
(
    select * 
      ,row_number() over (partition by TDate, TType order by TDate) rn 
    from @TableX 
) 
,RowsRN as 
(
    select tt.TDate 
      ,tt.TType 
      ,td.rn 
    from (select distinct TDate, TType 
      from @TableX 
      ) tt 
     full join (select distinct t1.TDate 
           ,row_number() over (partition by t1.TDate, t1.TType order by t1.TDate) rn 
        from @TableX t1 
       ) td 
      on(tt.TDate = td.TDate) 
) 
select r.TDate 
     ,r.TType 
     ,d.Fruit 
     ,d.Vegetable 
     ,d.Meat 
     ,d.Bread 
from DataRN d 
    full join RowsRN r 
     on(d.TDate = r.TDate 
      and d.TType = r.TType 
      and d.rn = r.rn 
      ) 
order by r.TDate 
     ,r.TType 
     ,isnull(d.Fruit,REPLICATE(CHAR(255),20)) 
     ,isnull(d.Vegetable,REPLICATE(CHAR(255),20)) 
     ,isnull(d.Meat,REPLICATE(CHAR(255),20)) 
     ,isnull(d.Bread,REPLICATE(CHAR(255),20)) 

あなたのコメントへの応答では、ここにあなたが得たやりなさい場合は、あなたが必要となる日付の完全なリストを生成するために、別のcteを使用する方法であります既に日付参照表(これらは非常に便利です):

declare @MinDate date = (select min(TDate) from @TableX); 
declare @MaxDate date = (select max(TDate) from @TableX); 

with Dates as 
(
    select @MinDate as DateValue 
    union all 
    select dateadd(d,1,DateValue) 
    from Dates 
    where DateValue < @MaxDate 
) 
select DateValue 
from Dates 
option (maxrecursion 0); 
+0

エレガントで素晴らしいソリューションです。御時間ありがとうございます。 – DaveX

+0

@DaveX心配しないで、あなたのためにうれしいよ:) – iamdave

+0

私の例では、日付/タイプコンボのエントリがゼロである可能性は考慮されていません。私がこれを実装したとき、私はそれを実現しました。しかし、1行だけを挿入することは基本的なので、克服するのは難しくありませんでした。 (その日付に一致する他のタイプがない場合は日付/タイプのコンボを検索し、すべてのヌルなどを含む行を挿入します)。私が考えることを忘れて、尋ねることについてちょうど面白い謝罪。 – DaveX

関連する問題