【问题标题】:SQL Server dynamic columns creationSQL Server 动态列创建
【发布时间】:2016-06-02 14:43:11
【问题描述】:

我有一个表格,其列和值如下

如何在第二个表格列中获取结果,其中 DYNAMIC 列名称为 - 首先是“prgmg_product_id”,该列的其余部分为“源 ID 1”、“源 ID 2”、“源 ID 3"

【问题讨论】:

标签: sql sql-server pivot


【解决方案1】:

要使用动态 SQL 实现此目的,以下内容将有所帮助:

CREATE TABLE #Prgmg (
    prgmg_product_id INT
    ,source_id_other INT
    );

INSERT #Prgmg (
    prgmg_product_id
    ,source_id_other
    )
VALUES (3310,11478)
    ,(3337,10833)
    ,(3354,11466)
    ,(4039,4846)
    ,(4039,65454)
    ,(4039,65456);

DECLARE @DYColumns NVARCHAR(1000)
    ,@DYSqlQuery NVARCHAR(4000);

--  CREATE THE COLUMNS REQUIRED
SET @DYColumns = STUFF((
            SELECT DISTINCT ',' 
                    + N'sourceID' 
                    + CAST(ROW_NUMBER() OVER (PARTITION BY prgmg_product_id ORDER BY prgmg_product_id, source_id_other) AS NVARCHAR(10))    
            FROM #Prgmg
            FOR XML PATH('')
            ), 1, 1, '');

-- CREATE THE DYNAMIC SQL AND ADD IN THE CREATED COLUMNS
SET @DYSqlQuery = '
    SELECT prgmg_product_id,' 
        +   @DYColumns 
        +   ' FROM (
                SELECT prgmg_product_id
                    ,CAST(N''sourceID'' + CAST(ROW_NUMBER() OVER (
                        PARTITION BY prgmg_product_id ORDER BY prgmg_product_id, source_id_other
                        ) AS NVARCHAR(10)) AS NVARCHAR(100)) AS Col
                    ,source_id_other
                FROM #Prgmg S1
        ) X
        PIVOT(MIN(source_id_other) FOR Col IN (' + @DYColumns + ')) P'

EXECUTE sp_executesql @DYSqlQuery;

虽然这确实为您提供了解决方案,但您应该花时间了解所使用的概念。例如使用ROW_NUMBER 创建所需的列以及如何映射到PIVOT 的使用。

【讨论】:

    【解决方案2】:

    我有一点时间把它扔到一起。我知道围绕 SO 的偏好是使用动态支点。我不太关心 sql server 中的 PIVOT。我发现语法非常迟钝。我更喜欢交叉表查询(也称为条件聚合)。额外的好处是,这种方法几乎总是比动态 PIVOT 稍快一些。

    您还必须意识到,这里发布的代码中有一半以上是在设置问题。将来,您应该以像这样的可消耗格式发布 ddl 和示例数据。这让我们更容易提供帮助。

    if OBJECT_ID('tempdb..#Something') is not null
        drop table #Something
    
    create table #Something
    (
        prgmg_product_id int,
        source_id_other int
    )
    
    insert #Something (prgmg_product_id, source_id_other) values
    (3310, 11478),
    (3337, 10833),
    (3354, 11466),
    (4039, 4846),
    (4039, 65454),
    (4039, 65456)
    
    declare @StaticPortion nvarchar(2000) = 
        'with OrderedResults as
        (
            select *, ROW_NUMBER() over(partition by prgmg_product_id order by source_id_other) as RowNum
            from #Something
        )
        select prgmg_product_id';
    
    declare @DynamicPortion nvarchar(max) = '';
    declare @FinalStaticPortion nvarchar(2000) = ' from OrderedResults Group by prgmg_product_id order by prgmg_product_id desc';
    
    with E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
    
    select @DynamicPortion = @DynamicPortion + 
        ', MAX(Case when RowNum = ' + CAST(N as varchar(6)) + ' then source_id_other end) as SourceID' + CAST(N as varchar(6)) + CHAR(10)
    from cteTally t
    where t.N <= 
    (
        select top 1 Count(*)
        from #Something
        group by prgmg_product_id
        order by COUNT(*) desc
    )
    
    declare @SqlToExecute nvarchar(max) = @StaticPortion + @DynamicPortion + @FinalStaticPortion;
    exec sp_executesql @SqlToExecute
    

    【讨论】:

      猜你喜欢
      • 2013-07-22
      • 2016-08-19
      • 1970-01-01
      • 2012-09-20
      • 2014-10-07
      • 1970-01-01
      • 1970-01-01
      • 2020-10-19
      • 2012-05-06
      相关资源
      最近更新 更多