SQL条件Pivot

时间:2010-05-06 03:18:36

标签: sql sql-server pivot

是的,这是另一个Pivot问题......我已经阅读了几乎所有以前的问题,我似乎无法将我所需要的查询整合在一起。

以下是我的表格:

FirmName    Account Balance Pmt Revolving   Installment     Mortgage
Amex    12345   10000   2000    1   0   0
Discover    54321   20000   4000    1   0   0
Chase   13579   100000  1500    0   0   1
Wells Fargo 2468    40000   900 0   1   0

最后三位列(Revolving,Installment和& Mortgage)规定了如何将列卷入一个类型。每个结果都需要三列,具体取决于类型及其行数。结果应该是一行有很多列。结果如下:

Revolving1_Firm Revolving1_Balance  Revolving1_Pmt  Revolving2_Firm    Revolving2_Balance   Revolving2_Pmt  Realestate1_Firm    Realestate1_Balance     Realestate1_Pmt Vehicle1_Firm   Vehicle1_Balance    Vehicle1_Pmt

Amex        10000   2000    Discover    20000   4000    Chase   100000  1500    Wells Fargo 40000   900

如何根据位字段(旋转,分期付款和抵押贷款)进行调整并保留正确的计数,以便每列都附加计数#?

1 个答案:

答案 0 :(得分:3)

这必须使用动态SQL来完成。首先,您需要确定每个类型的最大数量(并且可能还将3位列转换为单个LOAN_TYPE列,因为这是您的分区),然后使用ROW_NUMBER()OVER(PARTITION BY LOAN_TYPE ORDER BY FirmName) )超过与之相关的标准化数据,以便将事物放在右栏中。

我不得不问在数据库中执行此操作有多重要 - 因为架构不是固定的,所以很难看到这样做的实用程序。

尽管如此,只有比大多数动态枢轴稍微复杂一点,所以如果上面的提示没有让你到达那里,而你仍然希望我对它进行刺激,我会尝试稍后发布一些实际的工作代码

SET NOCOUNT ON

DECLARE @t AS TABLE
    (
     FirmName varchar(50) NOT NULL
    ,Account varchar(50) NOT NULL
    ,Balance money NOT NULL
    ,Pmt money NOT NULL
    ,Revolving bit NOT NULL
    ,Installment bit NOT NULL
    ,Mortgage bit NOT NULL
    ) ;
INSERT  INTO @t
VALUES  ('Amex', '12345', 10000, 2000, 1, 0, 0) ;
INSERT  INTO @t
VALUES  ('Discover', '54321', 20000, 4000, 1, 0, 0) ;
INSERT  INTO @t
VALUES  ('Chase', '13579', 100000, 1500, 0, 0, 1) ;
INSERT  INTO @t
VALUES  ('Wells Fargo', '2468', 40000, 900, 0, 1, 0) ;

WITH    n1
          AS (
              SELECT    FirmName
                       ,Account
                       ,Balance
                       ,Pmt
                       ,LoanType
                       ,LoanTypeFlag
              FROM      @t UNPIVOT ( LoanTypeFlag FOR LoanType IN ([Revolving], [Installment], [Mortgage]) ) AS unpvt
             ),
        n2
          AS (
              SELECT    FirmName
                       ,Balance
                       ,Pmt
                       ,LoanType
              FROM      n1
              WHERE     LoanTypeFlag = 1
             ),
        n3
          AS (
              SELECT    FirmName
                       ,Balance
                       ,Pmt
                       ,LoanType
                       ,ROW_NUMBER() OVER (PARTITION BY LoanType ORDER BY FirmName) AS SequenceNumber
              FROM      n2
             ),
        n4
          AS (
              SELECT    LoanType + CONVERT(varchar, SequenceNumber) AS Column_Prefix
                       ,FirmName AS Firm
                       ,CONVERT(varchar(50), Balance) AS Balance
                       ,CONVERT(varchar(50), Pmt) AS Pmt
              FROM      n3
             ),
        n5
          AS (
              SELECT    Column_Prefix + '_' + Col AS Col_Nm
                       ,Val
              FROM      n4 UNPIVOT ( Val FOR Col IN ([Firm], [Balance], [Pmt]) ) AS unpvt
             )
    SELECT  *
    FROM    n5 PIVOT ( MAX(Val) FOR Col_Nm IN ([Installment1_Firm], [Installment1_Balance], [Installment1_Pmt],
                                               [Mortgage1_Firm], [Mortgage1_Balance], [Mortgage1_Pmt], [Revolving1_Firm],
                                               [Revolving1_Balance], [Revolving1_Pmt], [Revolving2_Firm],
                                               [Revolving2_Balance], [Revolving2_Pmt]) ) AS pvt

你剩下的主要问题是最终的PIVOT列表(你可以像我提到的那样动态生成)和类型安全性,因为在最终PIVOT之前的实体值阶段,一切都符合varchar(50)。

此外,如果位标志不是互斥的,那么您将有一些重复...

我认为如果您使用的是表单生成系统,最终的PIVOT列表是相对固定的,那么您可以不使用动态SQL来生成该列表,但这会使系统略微不具备面向未来的能力。 / p>

这将生成pivot_list(可以简化):

WITH    n1
          AS (
              SELECT    FirmName
                       ,Account
                       ,Balance
                       ,Pmt
                       ,LoanType
                       ,LoanTypeFlag
              FROM      @t UNPIVOT ( LoanTypeFlag FOR LoanType IN ([Revolving], [Installment], [Mortgage]) ) AS unpvt
             ),
        n2
          AS (
              SELECT    FirmName
                       ,Balance
                       ,Pmt
                       ,LoanType
              FROM      n1
              WHERE     LoanTypeFlag = 1
             ),
        n3
          AS (
              SELECT    FirmName
                       ,Balance
                       ,Pmt
                       ,LoanType
                       ,ROW_NUMBER() OVER (PARTITION BY LoanType ORDER BY FirmName) AS SequenceNumber
              FROM      n2
             ),
        n4
          AS (
              SELECT    LoanType + CONVERT(varchar, SequenceNumber) AS Column_Prefix
                       ,FirmName AS Firm
                       ,CONVERT(varchar(50), Balance) AS Balance
                       ,CONVERT(varchar(50), Pmt) AS Pmt
              FROM      n3
             ),
        n5
          AS (
              SELECT    Column_Prefix + '_' + Col AS Col_Nm
                       ,Val
              FROM      n4 UNPIVOT ( Val FOR Col IN ([Firm], [Balance], [Pmt]) ) AS unpvt
             ),
        pivot_list(pivot_list)
          AS (
              SELECT    ',' + QUOTENAME(Col_Nm)
              FROM      n5
              FOR       XML PATH('')
             )
    SELECT  STUFF(pivot_list, 1, 1, '') AS pivot_list
    FROM    pivot_list