Rows Into Columns and Grouping

后端 未结 5 861
慢半拍i
慢半拍i 2021-02-06 07:28

I have a query that looks like this:

SELECT OrganizationName, OrganizationID, ReceivableStatus, InvoiceFee
FROM v_InvoicesFreelanceOutstanding
ORDER BY Organizat         


        
相关标签:
5条回答
  • 2021-02-06 07:51

    This looks like a job for pivot if you're using SQL Server 2005 or later.

    EDIT:

    Since you already know about pivot, you know it does almost what you need.

    You already have the following query:

    SELECT
        MAX(OrganizationName) as OrganizationName,
        OrganizationID,
        ReceivableStatus,
        SUM(InvoiceFee) as TotalDue
    FROM v_InvoicesFreelanceOutstanding
    GROUP BY OrganizationID, ReceivableStatus
    

    Which gives you the current, 30-60, 60-90 and 90+ parts that you need. If you pivot that, you get everything you need except for your total. So just throw in the total:

    (SELECT
        MAX(OrganizationName) as OrganizationName,
        OrganizationID,
        ReceivableStatus,
        SUM(InvoiceFee) as TotalDue
    FROM v_InvoicesFreelanceOutstanding
    GROUP BY OrganizationID, ReceivableStatus)
    UNION
    (SELECT
        MAX(OrganizationName) as OrganizationName,
        OrganizationID,
        'Total' AS ReceivableStatus,
        SUM(InvoiceFee) as TotalDue
    FROM v_InvoicesFreelanceOutstanding
    GROUP BY OrganizationID)
    

    Pivot on this result and you should get the output you want:

    SELECT *
    FROM 
        [the query above]
    PIVOT (
        SUM(TotalDue)
        FOR ReceivableStatus IN ([Current],[30-60 days],[60-90 days],[over 90 days],[Total]) 
    )
    
    0 讨论(0)
  • 2021-02-06 07:55

    PIVOT sucks. It has horrible syntax and isn't a PIVOT in the pivot table sense i.e. you have to know exactly how many columns will result in advance.

    It's probably easier to do a cross-tab report.

    SELECT 
    OrganizationName,
    OrganizationID,
    SUM(CASE WHEN ReceivableStatus       = '30-60 days' THEN InvoiceFee ELSE 0 END) AS [30 - 60 Days],
    SUM(CASE WHEN ReceivableStatus       = '60-90 days' THEN InvoiceFee ELSE 0 END) AS [60 - 90 Days],
    SUM(CASE WHEN ReceivableStatus       = '90-120 days' THEN InvoiceFee ELSE 0 END) AS [90 - 120 Days]
    
    FROM
    v_InvoicesFreelanceOutstanding
    GROUP BY OrganizationID
    
    0 讨论(0)
  • 2021-02-06 07:58

    I think your are searching for the pivot and unpivot functionality. Take a look at this: http://msdn.microsoft.com/en-us/library/ms177410.aspx

    0 讨论(0)
  • 2021-02-06 08:05

    Well, here is another pivot :)

    SET NOCOUNT ON
    
    DECLARE @table TABLE
    (   OrganizationName    VARCHAR(20),
        OrganizationID      INT,
        ReceivableStatus    VARCHAR(20),
        InvoiceFee      FLOAT
    )
    
    INSERT INTO @table
    SELECT 'Company A',139,'60-90 days',672.00 UNION
    SELECT 'Company A',139,'60-90 days',1800.00 UNION
    SELECT 'Company A',139,'over 90 days',1440.00 UNION
    SELECT 'Company B',264,'Current',3559.38 UNION
    SELECT 'Company B',264,'60-90 days',3785.50 UNION
    SELECT 'Company C',271,'60-90 days',446.25 UNION
    SELECT 'Company C',271,'over 90 days',637.50 UNION
    SELECT 'Company C',271,'over 90 days',1126.25
    
    --Specify Just the fields you want to return
    ;WITH COMPANYINFO(OrganizationName,OrganizationID,ReceivableStatus,InvoiceFee) AS
        (
        SELECT  OrganizationName,
            OrganizationID,
            ReceivableStatus,
            InvoiceFee
        FROM    @Table AS b 
        )
        SELECT * 
        FROM COMPANYINFO
        PIVOT
            (
            SUM(InvoiceFee)
            FOR ReceivableStatus
            IN ([Current],[60-90 days],[over 90 days])
            )
        AS P
        ORDER BY OrganizationName
    
    0 讨论(0)
  • 2021-02-06 08:06

    I have not used pivot before, so that may be your answer, but I've used brute force on a problem like this in the past and for you it would look something like:

    SELECT OrganizationName, SUM(Current) AS Current, SUM(3060Days) AS 3060Days, SUM(6090Days) AS 6090Days, SUM(Over90Days) As Over90Days, SUM(Total) AS Total
    FROM 
    (
    SELECT 
        OrganizationName,
        CASE WHEN ReceivableStatus = 'Current' THEN
            SUM(InvoiceFee)
        ELSE
            0
        END AS Current,
        CASE WHEN ReceivableStatus = '30-60 days' THEN
            SUM(InvoiceFee)
        ELSE
            0
        END AS 3060Days,
        CASE WHEN ReceivableStatus = '60-90 days' THEN
            SUM(InvoiceFee)
        ELSE
            0
        END AS 6090Days,
        CASE WHEN ReceivableStatus = 'over 90 days' THEN
            SUM(InvoiceFee)
        ELSE
            0
        END AS Over90Days,
        SUM(InvoiceFee) AS Total
    FROM v_InvoicesFreelanceOutstanding
    GROUP BY OrganizationName, ReceivableStatus) temp
    GROUP BY OrganizationName
    

    Basically, the inner query gives you results for each organization and a total for each individual category and the outer query aggregates all of them into single rows for each organization. Again, this may not be the most elegant or efficient way to go, but it is a way.

    0 讨论(0)
提交回复
热议问题