将两个 T-SQL 数据透视查询合并为一个

发布于 2024-08-15 05:28:47 字数 1532 浏览 4 评论 0原文

假设您有这个表:

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 

是否可以将这两个查询组合成一个更有效的查询?

Suppose you had this table:

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

Now a report needs to be created where the total records and the total special records are broken down by month. I can use these two queries separately:

--      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;

The results might look like this:

                  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 

Is it possible to combine these two queries into a single more efficient query?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

俯瞰星空 2024-08-22 05:28:47

我会这样做:

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

I would do it like this:

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
肩上的翅膀 2024-08-22 05:28:47

每个数据透视表只能有一个聚合 (COUNT(RecordId)),因此您所做的就是使用 UNION ALL 合并为一个结果集,并使用合适的额外列来标识每个数据透视表。

否则,您无法区分数据透视表中的 2 个不同聚合

You can only have one aggregate (COUNT(RecordId)) per pivot so all you do is combine into one result set with a UNION ALL with a suitable extra column to identify each pivot.

Otherwise, you have no way to distinguish the 2 different aggregates in the pivot

树深时见影 2024-08-22 05:28:47

感谢汤姆提供的解决方案,它回答了我的关键问题。

对我来说太糟糕了,我问错了问题。对于我的问题,我现在觉得最好使用像这样的简单分组查询:

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

然后剩下要做的就是在显示结果之前旋转结果。很高兴认识是吗?

Thanks for the solution Tom, that answers my pivot question.

Too bad for me I had the wrong question. For my problem I'm now feeling it would be better to use a plain grouping query like this instead:

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

Then all that is left to do is rotate the results before they are presented. Nice to know eh?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文