我可以使用 table 中的值将动态行数插入 table 中吗?

Can I insert a dynamic number of rows into a table using values from the table?

我想根据 table 中的信息向 table 中插入动态行数。

我可以使用下面的代码来完成,但我想知道是否有办法避免循环。

注释掉的部分是我尝试做的最好的尝试,但它给了我一个错误: "The reference to column "iCount" 不允许出现在 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 中有两个不同的 Tablix,最终行数相同,所以我的 headers 组显示在同一个地方在页面上。

像这样:

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))

为了回应您的评论,如果您还没有日期参考 table,这里是您将如何使用另一个 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);