【问题标题】:How Dynamicaly columns in UNPIVOT operatorUNPIVOT 运算符中的动态列
【发布时间】:2018-01-20 06:32:38
【问题描述】:

我目前有以下查询:

WITH History AS (
    SELECT
        kz.*,
        kz.__$operation AS operation,
        map.tran_begin_time as beginT, 
        map.tran_end_time as endT
    FROM cdc.fn_cdc_get_all_changes_dbo_EXT_GeolObject_KategZalezh(sys.fn_cdc_get_min_lsn('dbo_EXT_GeolObject_KategZalezh'), sys.fn_cdc_get_max_lsn(), 'all') AS kz 
        INNER JOIN  [cdc].[lsn_time_mapping] map
    ON kz.[__$start_lsn] = map.start_lsn
    where kz.GUID_BalanceHC_Zalezh = 'DDA9AB3A-A0AF-4623-9362-0000C8C83D63'
),
UnpivotedValues AS(
    SELECT  guid, GUID_another, field, val, operation, beginT, endT 
    FROM History
        UNPIVOT ( [val] FOR field IN
        (
            area, 
            oilwidthmin, 
            oilwidthmax, 
            efectivwidthmin, 
            efectivwidthmax, 
            etc...
        ))t
),
UnpivotedWithLastValue AS (
    SELECT 
        *,
        --Use LAG() to get the last value for the same field
        LAG(val, 1) OVER (PARTITION BY guid, GUID_another, field ORDER BY BeginT) LastVal
    FROM UnpivotedValues
)
SELECT * FROM UnpivotedWithLastValue WHERE val <> LastVal OR LastVal IS NULL ORDER BY guid

此查询返回已启用 CDC(更改数据捕获)的单个表的更改值。 我想创建一个存储过程,接收要取消透视的列,并将 cdc 函数(例如 cdc.fn_cdc_get_all_...)作为参数并返回结果集。

此表的结果必须合并到一个报告中。

在我的例子中,参数 1 是 cdc.fn_cdc_get_all_changes_dbo_EXT_GeolObject_KategZalezh(sys.fn_cdc_get_min_lsn('dbo_EXT_GeolObject_KategZalezh'), sys.fn_cdc_get_max_lsn(), 'all')。这是 CDC 功能。 我应该如何在结果中发送我想要的字段列表?弦如何? 另外,有没有办法不用动态SQL?动态 SQL 并不是更好的性能解决方案。

【问题讨论】:

  • 您能否概述一下您期望存储过程接收(参数)和返回(数据结果集)的内容。例如。该过程应该一次在多个 CDC 表上工作(即接收表列表作为参数),还是您希望为每个 CDC 表调用一次该过程?

标签: tsql stored-procedures sql-server-2012 parameter-passing unpivot


【解决方案1】:

如您所知,SQL Server 在设计上是声明性的,不支持宏替换。

UNPIVOT 显然会更高效,但这里有一个 UNPIVOT 的简化示例,它不需要动态 SQL,只需要一点 XML。

示例

假设您的表格/结果如下所示:

你可能会注意到,我只是在最后的 WHERE 中指定了要 EXCLUDE 的关键字段

Declare @YourData table (ID int,Active bit,First_Name varchar(50),Last_Name varchar(50),EMail varchar(50),Salary decimal(10,2))
Insert into @YourData values
(1,1,'John','Smith','john.smith@email.com',85600),
(2,0,'Jane','Doe'  ,'jane.doe@email.com',83200)

;with cte as (
    -- Replace with your Complex Query
    Select * from @YourData
)
Select A.ID
      ,A.Active
      ,C.*
 From  cte A
 Cross Apply (Select XMLData=cast((Select A.* for XML RAW) as xml)) B
 Cross Apply (
                Select Item   = attr.value('local-name(.)','varchar(100)')
                      ,Value  = attr.value('.','varchar(max)') 
                 From  XMLData.nodes('/row')    C1(n)
                 Cross Apply C1.n.nodes('./@*') C2(attr)
                 Where attr.value('local-name(.)','varchar(100)') not in ('ID','Active')
              ) C

退货

【讨论】:

    猜你喜欢
    • 2021-08-22
    • 1970-01-01
    • 2022-12-21
    • 2015-04-02
    • 1970-01-01
    • 1970-01-01
    • 2010-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多