2009-03-20 22 views
5

Ho una domanda che assomiglia a questo:righe in colonne e il raggruppamento

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

I dati che potrebbe essere simile a questo:

 
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 

Quello che voglio alla fine del display è qualcosa di simile (per i dati di cui sopra):

 
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 non è sufficiente a farmi superare questa:

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

che mostra qualcosa di simile (ancora una volta, dai dati di cui sopra):

 
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 

Che cosa allora? Qualsiasi aiuto sarebbe apprezzato.

Si noti che gli stati mostrati nella seconda tabella (Current, 30-60 days, 60-90 days, over 90 days) sono gli unici mi aspetto di venire sotto ReceivableStatus.

MODIFICA: Ci scusiamo per non averlo incluso. Sono a conoscenza di PIVOT ma non sono riuscito a farlo fare quello che voglio.

risposta

2

Questo sembra un lavoro per pivot se si utilizza SQL Server 2005 o successivo.

EDIT:

Dal momento che già si conosce pivot, sai che fa quasi quello che ti serve.

hai già la seguente query:

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

che vi dà la corrente, 30-60, 60-90 e 90+ parti che avete bisogno. Se lo fai ruotare, ottieni tutto ciò di cui hai bisogno, tranne il totale. Quindi, solo gettare la totale:

(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 su questo risultato e si dovrebbe ottenere l'output desiderato:

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

avrei dovuto essere più chiaro; Sono consapevole di PIVOT, non ero in grado di farlo fare ciò di cui ho bisogno. –

+0

Sono un deficiente. Il mio primo passaggio su PIVOT è quello che hai ma ho fatto SUM (InvoiceFee) invece di SUM (TotalDue) nella clausola PIVOT. Boohoo. Funziona, però. Grazie. –

+0

Tutti noi commettiamo errori. L'importante è che impariamo da loro. Sono solo felice di poterti aiutare. – Welbog

3

PIVOT fa schifo. Ha una sintassi orribile e non è un PIVOT nel senso della tabella pivot, cioè devi sapere esattamente quante colonne avranno il risultato in anticipo.

Probabilmente è più semplice eseguire un report a campi incrociati.

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

Come funzionerebbe con il GRUPPO, comunque? Voglio solo mostrare SUM (InvoiceFee) di 30-60 giorni nella colonna dei 30-60 giorni e così via. –

+0

E saprò quante colonne avremo in anticipo, quindi sono d'accordo con PIVOT se riuscirà a completare il lavoro, anche se la sintassi mi fa male alla testa. –

1

Non ho usato perno prima, in modo che possa essere la vostra risposta, ma ho usato la forza bruta su un problema come questo in passato e per voi sarebbe qualcosa di simile:

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 

In sostanza, la query interna fornisce risultati per ogni organizzazione e un totale per ogni singola categoria e la query esterna li aggrega in singole righe per ciascuna organizzazione. Ancora una volta, questo potrebbe non essere il modo più elegante o efficiente per andare, ma è un modo.

+0

+1. Anche se ha funzionato, è più grande di quanto speravo e ho fatto funzionare il PIVOT. Grazie comunque! –

2

Bene, qui è un altro perno :)

 
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

Ben fatto. Grazie. –

Problemi correlati