Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL动态unpivot表作为函数_Sql - Fatal编程技术网

SQL动态unpivot表作为函数

SQL动态unpivot表作为函数,sql,Sql,我目前有一个查询,我正在使用该查询取消对现有表的填充 表中的一些背景信息-每年都会向表中添加一个新列,以指示该年项目ID的$value。每增加一列,就会删除一列。所有这些列的前缀都是“YR_”,后面是新年。经常有20个“年”列 我被要求取消“YR_”列的标题,以便它们显示在下面,使我能够更容易地利用这些信息来编写多份报告- 在unpivot之前- ProjectID YR_16 YR_17 YR_18 YR_19 YR_20 10 0 100

我目前有一个查询,我正在使用该查询取消对现有表的填充

表中的一些背景信息-每年都会向表中添加一个新列,以指示该年项目ID的$value。每增加一列,就会删除一列。所有这些列的前缀都是“YR_”,后面是新年。经常有20个“年”列

我被要求取消“YR_”列的标题,以便它们显示在下面,使我能够更容易地利用这些信息来编写多份报告-

在unpivot之前-

ProjectID    YR_16   YR_17   YR_18   YR_19   YR_20
10           0       100     20      25      100
解聘后-

ProjectID    YR      Value
10           YR_16   0
10           YR_17   100
10           YR_18   20
10           YR_19   25
10           YR_20   100
下面是我用来创建unpivot表的查询,它将在添加/删除列时动态地拾取列

declare @query as NVARCHAR(max);
Declare @cols as NVARCHAR(250) = STUFF((
Select distinct ',' + QUOTENAME(Column_Name)
From INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = 'F1BWK_PLM_CAPEX'
And COLUMN_NAME like 'YR_%'
For XML Path(''), type)
.value('.','NVARCHAR(MAX)')
,1,1,'');

Select @query = 'With Unpivoted as 
(

Select * from F1BWK_PLM_CAPEX U

Unpivot (
Val
For Yr in (' + @cols + ')
)
As UnpivotTable 
)

Select U.*

From Unpivoted U
inner join [dbo].[F1_SYPAR_CTL] CTL
on CTL.value = U.WS_VERS
and CTL.PARAM_NAME like ''MBRC_CURR_PLM_BUDVER''
inner join [dbo].[F1_SYPAR_CTL] CTL2
on CTL2.value = U.WS_NAME
and CTL2.PARAM_NAME like ''MBRC_CURR_PLM_BUDWSH''';

Exec(@query);
我在将此查询转换为函数时遇到了一些问题,因此我可以调用它并将其保存在SQL Server中,以便我的团队的其他成员可以在需要时使用它

这是我第一次使用unpivot表并创建函数。欢迎关于更改动态unpivot查询以最适合我的需要的建议


提前感谢

在SQL Server中,不允许在函数中使用动态SQL

您可以创建一个SP,该SP将返回使用上述代码生成的记录集

更新:

为了完整起见: 您还可以使用()调用上面的SP,这将允许您连接到其他表,而无需先保存到临时表,但在我看来,这样做是一种很糟糕的方式

结束更新:

另一种方法是创建一个将取消透视此表的视图,并创建一个SP,该SP将在添加新列的过程完成后重新生成此视图,例如

CREATE TABLE F1BWK_PLM_CAPEX( Val INT, Yr_17 INT, Yr_18 INT )
INSERT INTO F1BWK_PLM_CAPEX
SELECT 1, 10, 12

CREATE VIEW F1BWK_PLM_CAPEX_UNPIVOTED
AS
    SELECT *
    FROM F1BWK_PLM_CAPEX AS U
    UNPIVOT (
        Val2 FOR Yr IN (Yr_17, Yr_18)
    )
    AS UnpivotTable;

CREATE PROCEDURE dbo.Create_F1BWK_PLM_CAPEX_UNPIVOTED
AS
    SET NOCOUNT ON

    DECLARE @query as NVARCHAR(max);
    DECLARE @cols as NVARCHAR(250) =
        STUFF((
            SELECT distinct ',' + QUOTENAME( Column_Name )
            FROM INFORMATION_SCHEMA.COLUMNS
            WHERE TABLE_NAME = 'F1BWK_PLM_CAPEX'
                AND COLUMN_NAME like 'YR_%'
            For XML Path(''), type)
            .value('.','NVARCHAR(MAX)' )
        ,1,1,'');

    SELECT @query = '
    ALTER VIEW F1BWK_PLM_CAPEX_UNPIVOTED
    AS
        SELECT *
        FROM F1BWK_PLM_CAPEX AS U
        UNPIVOT (
            Val2 FOR Yr IN ( ' + @cols + ' )
        )
        AS UnpivotTable 
    ';

    EXEC(@query);
RETURN;
现在,您的查询将变成:

SELECT *
FROM F1BWK_PLM_CAPEX_UNPIVOTED AS U
    INNER JOIN [dbo].[F1_SYPAR_CTL] AS CTL
        ON CTL.value = U.WS_VERS and CTL.PARAM_NAME = 'MBRC_CURR_PLM_BUDVER'
    INNER JOIN [dbo].[F1_SYPAR_CTL] AS CTL2
        ON CTL2.value = U.WS_NAME AND CTL2.PARAM_NAME = 'MBRC_CURR_PLM_BUDWSH'
年底,将运行一个流程,添加一个新列:

ALTER TABLE F1BWK_PLM_CAPEX
    ADD Yr_19 INT NOT NULL DEFAULT( 10 )
此进程需要运行此SP才能重新生成视图:

EXEC Create_F1BWK_PLM_CAPEX_UNPIVOTED
注意事项:

  • 我已经用
    =
    替换了
    LIKE
    ,因为您的查询与完整值匹配。仅当您需要指定通配符时才使用
    类似的
  • 我还修复了一个语法错误,在
    UNPIVOT
    查询中将Val更改为Val2

假设这是SQL Server,那么函数中就不能有动态SQL。非常感谢您花时间解释这一点并提供非常详细的解释。这真是一种享受,为我节省了很多时间和心痛。我对SQL Server还比较陌生,仍然在学习“正确的做事方式”,我已经大胆地在黑板上记下了您的笔记。@R.Ayres-还有一件事。请记住在视图中添加一条大注释,大意是“此视图由Create_F1BWK_PLM_CAPEX_UNPIVOTED自动生成。直接对视图所做的任何更改都将丢失。”。