Объединение двух сводных запросов T-SQL в один - PullRequest
0 голосов
/ 14 декабря 2009

Предположим, у вас была эта таблица:

CREATE TABLE Records
(
    RecordId       int IDENTITY(1,1) NOT NULL,
    CreateDate     datetime          NOT NULL,
    IsSpecial      bit               NOT NULL
    CONSTRAINT PK_Records   PRIMARY KEY(RecordId)
)

Теперь необходимо создать отчет, в котором общее количество записей и общее количество специальных записей разбиты по месяцам Я могу использовать эти два запроса отдельно:

--      TOTAL RECORDS PER MONTH
SELECT January, February, March, April, May, June,
    July, August, September, October, November, December
FROM (
    SELECT RecordId, DATENAME(MONTH, CreateDate) AS RecordMonth
    FROM dbo.Records
) AS SourceTable
PIVOT (
    COUNT(RecordId) FOR RecordMonth IN (January, February, March, April, May, June,
    July, August, September, October, November, December)
) AS PivotTable;

--      TOTAL SPECIAL RECORDS PER MONTH
SELECT January, February, March, April, May, June,
    July, August, September, October, November, December
FROM (
    SELECT RecordId, DATENAME(MONTH, CreateDate) AS RecordMonth
    FROM dbo.Records
    WHERE IsSpecial = 1
) AS SourceTable
PIVOT (
    COUNT(RecordId) FOR RecordMonth IN (January, February, March, April, May, June,
    July, August, September, October, November, December)
) AS PivotTable;

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

                  Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec
total              0     0    2     2     1      0     0    1      2     1     2    4
total special      0     0    1     0     1      0     0    0      0     0     0    2 

Можно ли объединить эти два запроса в один более эффективный запрос?

Ответы [ 3 ]

3 голосов
/ 14 декабря 2009

Я бы сделал это так:

SELECT
     CASE SQ.total_type
          WHEN 1 THEN 'total special'
          WHEN 2 THEN 'total expensive'
          ELSE 'total'
     END AS total_type,
     SUM(CASE WHEN MONTH(R.CreateDate) = 1 THEN 1 ELSE 0 END) AS January,
     SUM(CASE WHEN MONTH(R.CreateDate) = 2 THEN 1 ELSE 0 END) AS February,
     SUM(CASE WHEN MONTH(R.CreateDate) = 3 THEN 1 ELSE 0 END) AS March,
     ...
FROM
     dbo.Records R
INNER JOIN
     (
          SELECT 0 AS total_type UNION ALL   -- All
          SELECT 1 UNION ALL                 -- IsSpecial
          SELECT 2                           -- IsExpensive
     ) AS SQ ON
     (R.IsSpecial | (R.IsExpensive * 2)) & SQ.total_type = SQ.total_type
GROUP BY
     SQ.total_type
ORDER BY
     SQ.total_type DESC
2 голосов
/ 14 декабря 2009

У вас может быть только один агрегат (COUNT(RecordId)) на сводку, поэтому все, что вам нужно сделать, это объединить в один набор результатов с UNION ALL с подходящим дополнительным столбцом для идентификации каждой сводки.

В противном случае, у вас нет возможности различить 2 разных агрегата в своде

0 голосов
/ 16 декабря 2009

Спасибо за решение, Том, который отвечает на мой основной вопрос.

Жаль, у меня был неправильный вопрос. Теперь я чувствую, что для моей проблемы лучше использовать простой групповой запрос, подобный этому:

SELECT DATENAME(MONTH, CreateDate) AS Month,
    COUNT(*) AS Total,
    SUM(CASE
        WHEN IsSpecial = 1 THEN 1
        ELSE 0
    END) AS TotalSpecial,
    SUM(CASE
        WHEN IsExpensive = 1 THEN 1
        ELSE 0
    END) AS TotalExpensive
FROM Records
GROUP BY DATENAME(MONTH, CreateDate);

Тогда все, что осталось сделать, это повернуть результаты, прежде чем они будут представлены. Приятно знать, а?

...