SQL Server 动态 Pivot 为每个类别返回一行

Posted

技术标签:

【中文标题】SQL Server 动态 Pivot 为每个类别返回一行【英文标题】:SQL Server dynamic Pivot to return one row for each category 【发布时间】:2021-09-30 02:53:56 【问题描述】:

我的数据库是 SQL Server 2016。我们在 Excel 工作簿中接收源数据。包含源数据的工作表有四列。 EFFDATE 适用于所有负载类型和 Trans。这就是EFFDATE 的列为空的原因。

FieldName FieldData LoadType Trans
EFFDATE 7/1/2021 NULL NULL
FACILITYNUMBER 00109 V_HFR_Input_OPRate_LabRad_PHA_R BPRH
V.NetworkCode_PHA_999 999 V_HFR_Input_OPRate_LabRad_PHA_R BPRH
V.AccomCode_3 3 V_HFR_Input_OPRate_LabRad_PHA_R BPRH
V.LAB_PHA_ReimbType L V_HFR_Input_OPRate_LabRad_PHA_R BPRH
V.FFPHA_OPPassThru_LabRad V_HFR_Input_OPRate_LabRad_PHA_R BPRH
V.FFPHA_OPLCC_LabRad 0.6555 V_HFR_Input_OPRate_LabRad_PHA_R BPRH
V.Category LAB V_HFR_Input_OPRate_LabRad_PHA_R BPRH
V.Category RAD V_HFR_Input_OPRate_LabRad_PHA_R BPRH

在处理过程中,我们有一个应用程序通过 OLEDB 连接连接到 Excel 工作簿。原始数据被加载到数据库表中,触发器触发为字段名称和加载类型添加外键。表中数据如下所示

SeqNo FileKey FieldKey FieldName FieldData LoadTypeKey LoadType Trans
21 1002 1 EFFDATE 7/1/2021 0 NULL NULL
97 1002 3 FACILITYNUMBER 00109 16 V_HFR_Input_OPRate_LabRad_PHA_R BPRH
98 1002 29 V.NetworkCode_PHA_999 999 16 V_HFR_Input_OPRate_LabRad_PHA_R BPRH
99 1002 6 V.AccomCode_3 3 16 V_HFR_Input_OPRate_LabRad_PHA_R BPRH
100 1002 27 V.LAB_PHA_ReimbType L 16 V_HFR_Input_OPRate_LabRad_PHA_R BPRH
101 1002 17 V.FFPHA_OPPassThru_LabRad 16 V_HFR_Input_OPRate_LabRad_PHA_R BPRH
102 1002 15 V.FFPHA_OPLCC_LabRad 0.6555 16 V_HFR_Input_OPRate_LabRad_PHA_R BPRH
103 1002 26 V.Category LAB 16 V_HFR_Input_OPRate_LabRad_PHA_R BPRH
104 1002 32 V.Category RAD 16 V_HFR_Input_OPRate_LabRad_PHA_R BPRH

我有一个存储过程,可以将源数据的行动态地转换为单行,其中字段名称作为列标题,字段数据作为值。我对这组特定数据的问题是有两个类别,“LAB”和“RAD”。因为 SQL 数据透视需要一个聚合函数,所以我只返回一行。如果我使用PIVOT (MAX(FieldData) FOR FieldName,我会得到一行“RAD”。如果我使用PIVOT (MIN(FieldData) FOR FieldName,我会得到一行“LAB”。

如何制定查询以分别为 LAB 和 RAD 获取一行?所需的结果应与以下匹配。

FileKey SeqNo LoadTypeKey FacilityCode CategoryCode Network AccomCode EffectDate ReimburseType PassThruPct LowerCostChrg RatioCostChrg
1002 97 16 00109 LAB 999 3 7/1/2021 L 0.6555 NULL
1002 97 16 00109 RAD 999 3 7/1/2021 L 0.6555 NULL

【问题讨论】:

【参考方案1】:

这是一个非常奇怪的支点,但您可以为此使用窗口条件聚合:

SELECT *
FROM (
    SELECT
      FileKey,
      SeqNo,
      LoadTypeKey,
      FacilityCode = MAX(CASE WHEN FieldName = 'FACILITYNUMBER' THEN FieldData END) OVER (PARTITION BY FileKey),
      CategoryCode = FieldData,
      Network = MAX(CASE WHEN FieldName = 'V.NetworkCode_PHA_999' THEN FieldData END) OVER (PARTITION BY FileKey),
      AccomCode = MAX(CASE WHEN FieldName = 'V.AccomCode_3' THEN FieldData END) OVER (PARTITION BY FileKey),
      EffectDate = MAX(CASE WHEN FieldName = 'EFFDATE' THEN FieldData END) OVER (PARTITION BY FileKey),
      ReimburseType = MAX(CASE WHEN FieldName = 'V.LAB_PHA_ReimbType' THEN FieldData END) OVER (PARTITION BY FileKey),
      PassThruPct = MAX(CASE WHEN FieldName = 'V.FFPHA_OPPassThru_LabRad' THEN FieldData END) OVER (PARTITION BY FileKey),
      LowerCostChrg = MAX(CASE WHEN FieldName = 'V.FFPHA_OPLCC_LabRad' THEN FieldData END) OVER (PARTITION BY FileKey)
    FROM YourTable t
) t
WHERE FieldName = 'V.Category';

【讨论】:

以上是关于SQL Server 动态 Pivot 为每个类别返回一行的主要内容,如果未能解决你的问题,请参考以下文章

获取 ROWS 作为 COLUMNS(SQL Server 动态 PIVOT 查询)

SQL Server中Pivot()函数实现动态行转列

sql server动态行列转换

SQL Server中动态列转行

浅谈SQL Server 之 PIVOT运算符用法

SQL Server - 动态数据透视表 - SQL 注入