Reputation: 488384
I have a query that looks like this:
SELECT OrganizationName, OrganizationID, ReceivableStatus, InvoiceFee
FROM v_InvoicesFreelanceOutstanding
ORDER BY OrganizationID
The data from that might look like this:
OrganizationName OrganizationID ReceivableStatus InvoiceFee ----------------------------------------------------------------------------- Company A 139 60-90 days 672.00 Company A 139 60-90 days 1800.00 Company A 139 over 90 days 1440.00 Company B 264 Current 3559.38 Company B 264 60-90 days 3785.50 Company C 271 60-90 days 446.25 Company C 271 over 90 days 637.50 Company C 271 over 90 days 1126.25
What I want to eventually display is something like this (for the data above):
Company Current 30-60 days 60-90 days over 90 days Total ----------------------------------------------------------------------------- Company A 0 0 2472.00 0 2472.00 Company B 3559.38 0 3785.50 0 7344.88 Company C 0 0 446.25 1763.75 2210.00
My SQL-fu is not enough to get me past this:
SELECT
MAX(OrganizationName) as OrganizationName,
OrganizationID,
ReceivableStatus,
SUM(InvoiceFee) as TotalDue
FROM v_InvoicesFreelanceOutstanding
GROUP BY OrganizationID, ReceivableStatus
Which shows something like this (again, from the data above):
OrganizationName OrganizationID ReceivableStatus TotalDue ----------------------------------------------------------------------------- Company A 139 60-90 days 2472.00 Company A 139 over 90 days 1440.00 Company B 264 Current 3559.38 Company B 264 60-90 days 3785.50 Company C 271 60-90 days 446.25 Company C 271 over 90 days 1763.75
What then? Any help would be appreciated.
Note that the statuses shown in the 2nd table (Current
, 30-60 days
, 60-90 days
, over 90 days
) are the only ones I'm expecting to come up under ReceivableStatus
.
EDIT: Sorry for not including this. I am aware of PIVOT
but I couldn't get it to do what I want.
Upvotes: 11
Views: 35115
Reputation: 2793
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
Upvotes: 2
Reputation: 3096
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
Upvotes: 8
Reputation: 60398
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])
)
Upvotes: 4
Reputation: 9100
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.
Upvotes: 2
Reputation: 359
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
Upvotes: 0