Ряды в столбцы и группировки - PullRequest
6 голосов
/ 20 марта 2009

У меня есть запрос, который выглядит так:

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

Данные из этого могут выглядеть следующим образом:

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

То, что я хочу в конечном итоге отобразить, выглядит примерно так (для данных выше):

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

Моего SQL-фу недостаточно, чтобы пройти через это:

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

Что показывает что-то вроде этого (опять же из данных выше):

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

Что тогда? Любая помощь будет оценена.

Обратите внимание, что состояния, показанные во 2-й таблице (Current, 30-60 days, 60-90 days, over 90 days) - единственные, которые я ожидаю поднять под ReceivableStatus.

РЕДАКТИРОВАТЬ : Извините, что не включил это. Мне известно о PIVOT, но я не мог заставить его делать то, что я хочу.

Ответы [ 5 ]

5 голосов
/ 20 марта 2009

PIVOT отстой. Он имеет ужасный синтаксис и не является PIVOT в смысле сводных таблиц, т. Е. Вы должны точно знать, сколько столбцов получится заранее.

Вероятно, проще составить отчет в виде кросс-таблицы.

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
3 голосов
/ 20 марта 2009

Это похоже на задание для pivot, если вы используете SQL Server 2005 или более позднюю версию.

EDIT:

Поскольку вы уже знаете о pivot, вы знаете, что он делает почти то, что вам нужно.

У вас уже есть следующий запрос:

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

, который дает вам текущие, 30-60, 60-90 и 90+ частей, которые вам нужны. Если вы повернете это, вы получите все, что вам нужно, кроме вашей общей суммы. Так что просто добавьте в итоге:

(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)

Повернитесь к этому результату, и вы получите желаемый результат:

SELECT *
FROM 
    [the query above]
PIVOT (
    SUM(TotalDue)
    FOR ReceivableStatus IN ([Current],[30-60 days],[60-90 days],[over 90 days],[Total]) 
)
2 голосов
/ 20 марта 2009

Ну, вот еще один пивот:)

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
2 голосов
/ 20 марта 2009

Я раньше не использовал pivot, так что это может быть вашим ответом, но я использовал грубую силу для такой проблемы в прошлом, и для вас это будет выглядеть примерно так:

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

По сути, внутренний запрос дает результаты для каждой организации и итоги для каждой отдельной категории, а внешний запрос объединяет их все в отдельные строки для каждой организации. Опять же, это может быть не самый элегантный или эффективный путь, но это путь.

0 голосов
/ 20 марта 2009

Я думаю, что вы ищете функцию поворота и отмены поворота. Взгляните на это: http://msdn.microsoft.com/en-us/library/ms177410.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...