SQL Server:尝试将“矩阵”展平为一行

时间:2017-01-31 17:00:30

标签: sql-server row type-conversion

我有一个Y和N的“矩阵”,如下图所示,Id lile是下面的图像,其中每个SID将其展平成1行,显示一行上的所有Y和Ns就像我是ORing行中的数据。我可以在SQL Server中执行此操作吗?

enter image description here

enter image description here

这是我的原始查询

SELECT  TERM_SID,
  CASE WHEN d2.DATA_CLASSIFICATION_DESC='Public data' THEN 'Y' ELSE 'N' END AS 'PUBLIC',
  CASE WHEN d2.DATA_CLASSIFICATION_DESC='Public data in aggregate' THEN 'Y'  ELSE 'N' END as 'PUBLIC_AGGREGATE',
  CASE WHEN d2.DATA_CLASSIFICATION_DESC='Internal data' THEN 'Y'  ELSE 'N' END as 'INTERNAL',
  CASE WHEN d2.DATA_CLASSIFICATION_DESC='Internal data in aggregate' THEN 'Y'  ELSE 'N' END as 'INTERNAL_AGGREGATE',
  CASE WHEN d2.DATA_CLASSIFICATION_DESC='Limited data' THEN 'Y'  ELSE 'N' END as 'LIMITED',
  CASE WHEN d2.DATA_CLASSIFICATION_DESC='Restricted data' THEN 'Y'  ELSE 'N' END as 'RESTRICTED'
  FROM [UDW_DATA_DICTIONARY].[dbo].[DATA_CLASSIFICATION] d2
  JOIN [UDW_DATA_DICTIONARY].[dbo].[DATA_CLASSIFICATION_MAPPING] dm2 ON dm2.DATA_CLASSIFICATION_SID=d2.DATA_CLASSIFICATION_SID order by TERM_SID

以及我在转换'Y'= 1'N'= 0

后尝试对各列进行求和
select * from
      (
      SELECT  TERM_SID,
      CASE WHEN d2.DATA_CLASSIFICATION_DESC='Public data' THEN 1 ELSE 0 END AS 'PUBLIC',
      CASE WHEN d2.DATA_CLASSIFICATION_DESC='Public data in aggregate' THEN 1  ELSE 0 END as 'PUBLIC_AGGREGATE',
      CASE WHEN d2.DATA_CLASSIFICATION_DESC='Internal data' THEN 1  ELSE 0 END as 'INTERNAL',
      CASE WHEN d2.DATA_CLASSIFICATION_DESC='Internal data in aggregate' THEN 1  ELSE 0 END as 'INTERNAL_AGGREGATE',
      CASE WHEN d2.DATA_CLASSIFICATION_DESC='Limited data' THEN 1  ELSE 0 END as 'LIMITED',
      CASE WHEN d2.DATA_CLASSIFICATION_DESC='Restricted data' THEN 1  ELSE 0 END as 'RESTRICTED'
      FROM [UDW_DATA_DICTIONARY].[dbo].[DATA_CLASSIFICATION] d2
      JOIN [UDW_DATA_DICTIONARY].[dbo].[DATA_CLASSIFICATION_MAPPING] dm2 ON dm2.DATA_CLASSIFICATION_SID=d2.DATA_CLASSIFICATION_SID 
      ) x
      PIVOT
      (sum (x.PUBLIC) for TERM_SID in (*)) as piv

但我在x.PUBLIC上看到错误,请参阅下面的图片

enter image description here

感谢SqlZim,这就是我想出来的

select TERM_SID
,max(PUBLICDATA) as PublicData
,max(PUBLIC_AGGREGATE) as Public_AGGregate
,max(INTERNAL) as Internal
,max(INTERNAL_AGGREGATE) as internal_Aggregate
,max(LIMITED) as Limited
,max(RESTRICTED) as Restricted
from
(
      SELECT  TERM_SID,
      CASE WHEN d2.DATA_CLASSIFICATION_DESC='Public data' THEN 'Y' ELSE 'N' END AS 'PUBLICDATA',
      CASE WHEN d2.DATA_CLASSIFICATION_DESC='Public data in aggregate' THEN 'Y'  ELSE 'N' END as 'PUBLIC_AGGREGATE',
      CASE WHEN d2.DATA_CLASSIFICATION_DESC='Internal data' THEN 'Y'  ELSE 'N' END as 'INTERNAL',
      CASE WHEN d2.DATA_CLASSIFICATION_DESC='Internal data in aggregate' THEN 'Y'  ELSE 'N' END as 'INTERNAL_AGGREGATE',
      CASE WHEN d2.DATA_CLASSIFICATION_DESC='Limited data' THEN 'Y'  ELSE 'N' END as 'LIMITED',
      CASE WHEN d2.DATA_CLASSIFICATION_DESC='Restricted data' THEN 'Y'  ELSE 'N' END as 'RESTRICTED'
      FROM [UDW_DATA_DICTIONARY].[dbo].[DATA_CLASSIFICATION] d2
      JOIN [UDW_DATA_DICTIONARY].[dbo].[DATA_CLASSIFICATION_MAPPING] dm2 ON dm2.DATA_CLASSIFICATION_SID=d2.DATA_CLASSIFICATION_SID
) mat
group by Term_SID

这也可以使用建议的CTE格式

with mat  (TERM_SID,PUBLICDATA,PUBLIC_AGGREGATE,INTERNAL,INTERNAL_AGGREGATE,LIMITED,RESTRICTED)
as
(
      SELECT  dm2.TERM_SID
             ,CASE WHEN d2.DATA_CLASSIFICATION_DESC = 'Public data' THEN 'Y' ELSE 'N' END AS PUBLICDATA
             ,CASE WHEN d2.DATA_CLASSIFICATION_DESC = 'Public data in aggregate' THEN 'Y'  ELSE 'N' END as PUBLIC_AGGREGATE
             ,CASE WHEN d2.DATA_CLASSIFICATION_DESC = 'Internal data' THEN 'Y'  ELSE 'N' END as INTERNAL
             ,CASE WHEN d2.DATA_CLASSIFICATION_DESC = 'Internal data in aggregate' THEN 'Y'  ELSE 'N' END as INTERNAL_AGGREGATE
             ,CASE WHEN d2.DATA_CLASSIFICATION_DESC = 'Limited data' THEN 'Y'  ELSE 'N' END as LIMITED
             ,CASE WHEN d2.DATA_CLASSIFICATION_DESC = 'Restricted data' THEN 'Y'  ELSE 'N' END as RESTRICTED
      FROM [UDW_DATA_DICTIONARY].[dbo].[DATA_CLASSIFICATION] d2
          JOIN [UDW_DATA_DICTIONARY].[dbo].[DATA_CLASSIFICATION_MAPPING] dm2
              ON dm2.DATA_CLASSIFICATION_SID = d2.DATA_CLASSIFICATION_SID
)
select m1.TERM_SID
      ,max(m1.PUBLICDATA) as PublicData
      ,max(m1.PUBLIC_AGGREGATE) as Public_AGGregate
      ,max(m1.INTERNAL) as Internal
      ,max(m1.INTERNAL_AGGREGATE) as internal_Aggregate
      ,max(m1.LIMITED) as Limited
      ,max(m1.RESTRICTED) as Restricted
      ,count(1) as mat2count
from mat m1
    left join mat m2
        on(m1.TERM_SID = m2.TERM_SID)
group by m1.Term_SID

1 个答案:

答案 0 :(得分:2)

我不确定第二张图片中Term_SID=3的两行是怎么回事,但这会让你更接近:

;with mat as (
  select  
      term_sid
    , [Public] = case 
        when d2.data_classification_desc='Public data'
          then 'Y' else 'N' end
    , [Public_Aggregate] = case 
        when d2.data_classification_desc='Public data in aggregate'
          then 'Y'  else 'N' end
    , [Internal] = case 
        when d2.data_classification_desc='Internal data' 
          then 'Y'  else 'N' end
    , [Internal_Aggregate] = case 
        when d2.data_classification_desc='Internal data in aggregate'
          then 'Y'  else 'N' end
    , [Limited] = case 
        when d2.data_classification_desc='Limited data'
          then 'Y'  else 'N' end
    , [Restricted] = case 
        when d2.data_classification_desc='Restricted data' 
          then 'Y'  else 'N' end 
    from [udw_data_dictionary].[dbo].[data_classification] d2
      join [udw_data_dictionary].[dbo].[data_classification_mapping] dm2 
        on dm2.data_classification_sid=d2.data_classification_sid 
)

select
      Term_SID
    , Public             = max(Public)
    , Public_Aggregate   = max(Public_Aggregate)
    , Internal           = max(Internal)
    , Internal_Aggregate = max(Internal_Aggregate)
    , Limited            = max(Limited)
    , Restricted         = max(Restricted)
  from mat
  group by Term_SID
  order by term_sid