Cách tạo pivot bằng sql

Oct 30 2020

Tôi mới làm quen với SQL, tôi có một bảng như thế này.

Dưới đây là truy vấn:

select 
    gc.GC_Name, dt.GC_SectorType, dt.ageing,
    sum(cast(dt.[Brokerage Debtors] as numeric)) as Brokerage_Amt,
    dt.divisionalofficename  
from
    [AR].[Fact_Brokerage_Debt] dt 
inner join 
    AUM.DIM_BUSINESS_TYPE BT on BT.Business_Type_WId_PK = dt.BusinessType_WID 
inner join 
    aum.Dim_GroupCompany gc on dt.insurer_Wid = gc.GC_WID
where 
    bt.Business_Type_Wid in (4, 8, 10) 
    and dt.ageing <> '<30' 
    and cast(dt.[Brokerage Debtors] as numeric) > 0 
    and gc.GC_SectorType = 'psu'
group by  
    gc.GC_Name, dt.GC_SectorType, dt.ageing, dt.divisionalofficename 

[sql_table]

Và tôi được yêu cầu lấy dữ liệu như thế này

[request_format]

Grandtotaldựa trên tổng số brockrage_amt.

Tôi hiểu rằng tôi cần sử dụng chức năng PIVOT. Nhưng không thể hiểu nó một cách rõ ràng. Sẽ rất hữu ích nếu ai đó có thể giải thích nó trong trường hợp trên. (Hoặc bất kỳ lựa chọn thay thế nào nếu có)

Trả lời

1 TimMylott Oct 30 2020 at 20:45

Tôi đã giả định rằng Tổng số tiền dựa trên Tên bảo hiểm và Mã DO và Tổng số tiền lớn là tổng và không được tính. Cũng có một số khác biệt giữa tên trường trong truy vấn của bạn, sql_table và request_format. Mã mẫu dưới đây sẽ phải được điều chỉnh theo tình huống cụ thể của bạn, nhưng đó là cấu trúc và định dạng cơ bản mà bạn đang yêu cầu.

Ngoài ra, bạn sẽ không nhận được request_format chính xác vì kết quả truy vấn sẽ không có màu sắc, định dạng, v.v.

Đây là một ví dụ làm việc với dữ liệu mẫu đã tạo:

DECLARE @testdata TABLE
    (
        [Insurance_Name] VARCHAR(100)
      , [DO_Code] VARCHAR(100)
      , [ageing] VARCHAR(10)
      , [Brokerage_Amt] INT
    );

INSERT INTO @testdata (
                          [Insurance_Name]
                        , [DO_Code]
                        , [ageing]
                        , [Brokerage_Amt]
                      )
VALUES ( 'Insurance Company 1', '123', '31-60', 100 )
     , ( 'Insurance Company 1', '123', '91-120', 200 )
     , ( 'Insurance Company 1', '123', '>=365', 300 )
     , ( 'Insurance Company 1', '234', '61-90', 300 )
     , ( 'Insurance Company 1', '234', '61-90', 300 )
     , ( 'Insurance Company 1', '234', '121-180', 300 )
     , ( 'Insurance Company 1', '234', '181-364', 200 )
     , ( 'Insurance Company 2', '789', '61-90', 50 )
     , ( 'Insurance Company 2', '789', '121-180', 25 )
     , ( 'Insurance Company 2', '789', '181-364', 9 );

SELECT [pvt].[Insurance_Name]
     , [pvt].[DO_Code]
     , [31-60]
     , [61-90]
     , [91-120]
     , [121-180]
     , [181-364]
     , [>=365]
     , [pvt].[GrandTotal]
FROM   (
           SELECT [Insurance_Name]
                , [DO_Code]
                , [ageing]
                , [Brokerage_Amt]
                , SUM([Brokerage_Amt]) OVER ( PARTITION BY [Insurance_Name]
                                                         , [DO_Code]
                                            ) AS [GrandTotal] --here we determine that grand total based on the Insurance_Name and DO_Code
           FROM   @testdata
       ) AS [ins]
PIVOT (
          SUM([Brokerage_Amt]) --aggregate and pivot this column
          FOR [ageing] --sum the above and make column where the value is one of these [31-60], [61-60], etc...
          IN ( [31-60], [61-90], [91-120], [121-180], [181-364], [>=365] )
      ) AS [pvt];

Cung cấp cho bạn kết quả của:

Insurance_Name            DO_Code    31-60       61-90       91-120      121-180     181-364     >=365       GrandTotal
------------------------  ---------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
Insurance Company 1       123        100         NULL        200         NULL        NULL        300         600
Insurance Company 1       234        NULL        600         NULL        300         200         NULL        1100
Insurance Company 2       789        NULL        50          NULL        25          9           NULL        84

Không có dữ liệu mẫu nên tôi đoán việc cố gắng điều chỉnh lại truy vấn của bạn sẽ giống như sau:

 SELECT [pvt].[Insurance_Name]
     , [pvt].[DO_Code]
     , [31-60]
     , [61-90]
     , [91-120]
     , [121-180]
     , [181-364]
     , [>=365]
     , [pvt].[GrandTotal]
FROM   (
           SELECT     [gc].[GC_Name] AS [Insurance_Name]
                    , [dt].[GC_SectorType] AS [DO_Code]
                    , [dt].[ageing]
                    --, SUM(CAST([dt].[Brokerage Debtors] AS NUMERIC)) AS [Brokerage_Amt]
                    , CAST([dt].[Brokerage Debtors] AS NUMERIC) AS [Brokerage_Amt]
                    , SUM(CAST([dt].[Brokerage Debtors] AS NUMERIC)) OVER (PARTITION BY [gc].[GC_Name], [dt].[GC_SectorType]) AS GrandTotal
                    , [dt].[divisionalofficename]
           FROM       [AR].[Fact_Brokerage_Debt] [dt]
           INNER JOIN [AUM].[DIM_BUSINESS_TYPE] [BT]
               ON [BT].[Business_Type_WId_PK] = [dt].[BusinessType_WID]
           INNER JOIN [aum].[Dim_GroupCompany] [gc]
               ON [dt].[insurer_Wid] = [gc].[GC_WID]
           WHERE      [BT].[Business_Type_Wid] IN ( 4, 8, 10 )
                      AND [dt].[ageing] <> '<30'
                      AND CAST([dt].[Brokerage Debtors] AS NUMERIC) > 0
                      AND [gc].[GC_SectorType] = 'psu'
       --I guess you would not need the sum and group by, sum should be hanlded in the pivot, but above we add a sum partioning by [gc].[GC_Name], [dt].[GC_SectorType] for the grand total
       --GROUP BY   [gc].[GC_Name]
       --         , [dt].[GC_SectorType]
       --         , [dt].[ageing]
       --         , [dt].[divisionalofficename];
       ) AS [ins]
PIVOT (
          SUM([Brokerage_Amt]) --aggregate and pivot this column
          FOR [ageing] --sum the above and make column where the value is one of these [31-60], [61-60], etc...
          IN ( [31-60], [61-90], [91-120], [121-180], [181-364], [>=365] )
      ) AS [pvt];

Tôi suy đoán rằng sẽ cần phải có những thay đổi vì không có dữ liệu mẫu và định nghĩa bảng được cung cấp. Vì tôi không thể chạy truy vấn nên có thể có lỗi chính tả.