2009-03-20 25 views
5

Ich habe eine Abfrage, die wie folgt aussieht:Zeilen in Spalten und gruppieren

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

Die Daten aus, dass könnte wie folgt aussehen:

 
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 

Was ich will schließlich ist Anzeige so etwas wie dieses (für die Daten oben):

 
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 nicht genug ist, mich daran vorbei:

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

Das zeigt, wie diese etwas (wieder aus den obigen Daten):

 
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 

Was dann? Jede Hilfe wäre willkommen.

Beachten Sie, dass die Zustände in der zweiten Tabelle dargestellt (Current, 30-60 days, 60-90 days, over 90 days) sind die einzigen, die ich erwarte unter ReceivableStatus zu kommen.

BEARBEITEN: Sorry für das nicht einschließlich dies. Ich bin mir bewusst, PIVOT, aber ich konnte es nicht tun, was ich will.

Antwort

2

Dies sieht aus wie ein Job für pivot, wenn Sie SQL Server 2005 oder höher verwenden.

EDIT:

Da Sie bereits über pivot wissen, wissen Sie, es macht fast, was Sie brauchen.

Sie haben bereits die folgende Abfrage:

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

dem Sie die aktuelle gibt, 30-60, 60-90 und 90+ Teile, die Sie benötigen. Wenn du das drehst, bekommst du alles, was du brauchst, außer deiner Summe. So werfen nur in der Gesamt:

(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 auf diesem Ergebnis, und Sie sollten die Ausgabe, die Sie erhalten möchten:

SELECT * 
FROM 
    [the query above] 
PIVOT (
    SUM(TotalDue) 
    FOR ReceivableStatus IN ([Current],[30-60 days],[60-90 days],[over 90 days],[Total]) 
) 
+0

ich klarer sein sollte; Ich bin PIVOT bewusst, ich konnte es einfach nicht machen, was ich brauche. –

+0

Ich bin ein Idiot. Mein erster Weg zum PIVOT ist, was Sie haben, aber ich habe SUM (InvoiceFee) anstelle von SUM (TotalDue) in der PIVOT-Klausel. Bouhoo. Es funktioniert aber. Vielen Dank. –

+0

Wir machen alle Fehler. Wichtig ist, dass wir von ihnen lernen. Ich bin nur froh, dass ich helfen konnte. – Welbog

3

PIVOT saugt. Es hat eine schreckliche Syntax und ist kein PIVOT in der Pivot-Tabellen-Richtung, d. H. Sie müssen genau wissen, wie viele Spalten im Voraus resultieren.

Es ist wahrscheinlich einfacher, einen Kreuztabellenbericht zu erstellen.

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

Wie würde das mit der GROUP funktionieren? Ich möchte nur den SUM (InvoiceFee) von 30-60 Tagen in der Spalte 30-60 Tage anzeigen, und so weiter. –

+0

Und ich werde wissen, wie viele Spalten im Voraus entstehen, also bin ich mit PIVOT in Ordnung, wenn es die Arbeit erledigt, obwohl die Syntax meinen Kopf schmerzt. –

1

ich Pivot nicht verwendet haben, kann, so dass Ihre Antwort sein, aber ich habe auf ein Problem wie dies in der Vergangenheit Brute-Force eingesetzt und für Sie wäre es so etwas wie folgt aussehen:

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 

Im Grunde liefert die innere Abfrage Ergebnisse für jede Organisation und eine Gesamtsumme für jede einzelne Kategorie und die äußere Abfrage aggregiert alle in einzelne Zeilen für jede Organisation. Auch dies ist vielleicht nicht der eleganteste oder effizienteste Weg, aber es ist ein Weg.

+0

+1. Obwohl es funktioniert hat, ist es größer als ich gehofft hatte und ich habe den PIVOT arbeiten lassen. Trotzdem danke! –

2

Nun, hier ist eine weitere Dreh :)

 
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

Schön gemacht. Vielen Dank. –

Verwandte Themen