【问题标题】:PIVOT SQL - GuidancePIVOT SQL - 指导
【发布时间】:2018-06-04 06:43:37
【问题描述】:

我有以下代码:

    SELECT * 
    FROM
        (   
        SELECT p.ProductID, pc.Name, ISNULL(p.Color, 'Uncolored') AS Color
        FROM SalesLT.ProductCategory AS pc
        INNER JOIN SalesLT.Product AS p ON pc.ProductCategoryID = p.ProductCategoryID
        )
    AS PPC
    PIVOT (COUNT(ProductID) FOR COLOR IN ([Red], [Blue], [Black], [Silver], [Yellow], [Grey], [Multi], [Uncolored]))
    AS ColorPivotTable

这给出了以下输出:

我想知道将 Total 列应用于此的最佳方法

期望的输出

非常感谢您提供任何反馈。

【问题讨论】:

  • 解释“应用总列”应该是什么意思。
  • 嗨,这是一个按颜色汇总所有产品的总列(在“未着色列”的右侧),即总共 32 辆山地自行车。还有一个底部的总列,按颜色汇总所有产品
  • @GordonLinoff 我在想也许汇总可能会满足 OP,但我不知道如何在这里做到这一点。
  • 你可以得到一个 cte 的总数,然后加入它
  • 请阅读meta.stackoverflow.com/questions/285551/… 和接受的答案

标签: sql sql-server tsql pivot


【解决方案1】:

您可以在这里找到类似的问题:

Using pivot table with column and row totals in sql server 2008

使用 CUBE,一个解决方案可能是

WITH SalesLT_ProductCategory as (
    SELECT * FROM (
        VALUES 
            (1, 'Mountain Bikes'),
            (2, 'Road Bikes'),
            (3, 'Touring Bikes'),
            (4, 'Brakes')
            -- etc...
        ) AS a (ProductCategoryID, Name)
), SalesLT_Product AS (
    SELECT * FROM (
        VALUES 
            (1, 1, 'Red'),
            (1, 1, 'Blue'),
            (1, 1, 'Blue'),
            (1, 1, 'Blue'),

            (1, 2, 'Red'),
            (1, 2, 'Red'),
            (1, 2, 'Blue'),
            (1, 2, 'Black'),

            (1, 3, 'Black'),
            (1, 3, 'Yellow'),
            (1, 3, 'Grey'),
            (1, 3, 'Grey'),
            (1, 3, 'Grey'),

            (1, 4, 'Red'),
            (1, 4, 'Multi'),
            (1, 4, 'Multi'),
            (1, 4, 'Uncolored'),
            (1, 4, 'Uncolored'),
            (1, 4, 'Uncolored')
            -- etc...
        ) AS a (ProductID, ProductCategoryID, Color)
), BaseData AS (
        SELECT p.ProductID, pc.Name, ISNULL(p.Color, 'Uncolored') AS Color
        FROM SalesLT_ProductCategory AS pc
        INNER JOIN SalesLT_Product AS p ON pc.ProductCategoryID = p.ProductCategoryID
)
SELECT
  Name, 
  COALESCE(Red, 0) AS Red, 
  COALESCE(Blue, 0) AS Blue, 
  COALESCE(Black, 0) AS Black, 
  COALESCE(Silver, 0) AS Silver, 
  COALESCE(Yellow, 0) AS Yellow, 
  COALESCE(Grey, 0) AS Grey, 
  COALESCE(Multi, 0) AS Multi, 
  COALESCE(Uncoloured, 0) AS Uncoloured, 
  Total
FROM (
  SELECT
    COALESCE(Name, 'Total') AS Name, 
    COALESCE(Color, 'Total') AS Color, 
    COUNT(*) AS Count
  FROM BaseData
  GROUP BY CUBE (Name, Color)
) AS t
PIVOT (
  SUM(Count) FOR Color IN (
    Red, Blue, Black, Silver, Yellow, 
    Grey, Multi, Uncoloured, Total
  )
) AS p
ORDER BY CASE Name WHEN 'Total' THEN 1 ELSE 0 END, Name

使用 CTE,可以替代解决方案

WITH SalesLT_ProductCategory as (
    SELECT * FROM (
        VALUES 
            (1, 'Mountain Bikes'),
            (2, 'Road Bikes'),
            (3, 'Touring Bikes'),
            (4, 'Brakes')
            -- etc...
        ) AS a (ProductCategoryID, Name)
), SalesLT_Product as (
    SELECT * FROM (
        VALUES 
            (1, 1, 'Red'),
            (1, 1, 'Blue'),
            (1, 1, 'Blue'),
            (1, 1, 'Blue'),

            (1, 2, 'Red'),
            (1, 2, 'Red'),
            (1, 2, 'Blue'),
            (1, 2, 'Black'),

            (1, 3, 'Black'),
            (1, 3, 'Yellow'),
            (1, 3, 'Grey'),
            (1, 3, 'Grey'),
            (1, 3, 'Grey'),

            (1, 4, 'Red'),
            (1, 4, 'Multi'),
            (1, 4, 'Multi'),
            (1, 4, 'Uncolored'),
            (1, 4, 'Uncolored'),
            (1, 4, 'Uncolored')
            -- etc...
        ) AS a (ProductID, ProductCategoryID, Color)
), PivotData AS (
    -- your query
    SELECT * 
    FROM
        (   
        SELECT p.ProductID, pc.Name, ISNULL(p.Color, 'Uncolored') AS Color
        FROM SalesLT_ProductCategory AS pc
        INNER JOIN SalesLT_Product AS p ON pc.ProductCategoryID = p.ProductCategoryID
        )
    AS PPC
    PIVOT (COUNT(ProductID) FOR COLOR IN ([Red], [Blue], [Black], [Silver], [Yellow], [Grey], [Multi], [Uncolored]))
    AS ColorPivotTable
), ColumnTotals AS (
    -- column totals
    SELECT
          'Total' AS Name
        , SUM(Red) AS Red
        , SUM(Blue) AS Blue
        , SUM(Black) AS Black
        , SUM(Silver) AS Silver
        , SUM(Yellow) AS Yellow
        , SUM(Grey) AS Grey
        , SUM(Multi) AS Multi
        , SUM(Uncolored )AS Uncolored
    FROM PivotData
), PivotDataWithRowTotals AS (
SELECT * FROM PivotData
UNION ALL 
SELECT * FROM ColumnTotals
)
SELECT P.*
    -- row totals
    , P.Red + P.Blue + P.Black + P.Silver + P.Yellow + P.Grey + P.Multi + P.Uncolored as Total
FROM PivotDataWithRowTotals AS P

【讨论】:

  • 您的手册 UNION ALL 连接可以使用 CUBEROLLUP / GROUPING SETS 简化,具体取决于用例。正如我所展示的那样,您可能会得到更好的计划in this blog post
  • 感谢您的建议,我将尝试发布使用 CUBO/ROLLUP 的替代解决方案,如帖子stackoverflow.com/questions/17140559/…
【解决方案2】:

这是CUBE() (or GROUPING SETS) calculationPIVOT representationI had to write a blog post about it 结合的一个很好的例子。

这里的解决方案可以完全满足您的需求:

WITH Bikes(Name, Colour) AS (
  SELECT * FROM (
    VALUES ('Mountain Bikes', 'Black'), 
           ('Mountain Bikes', 'Black'),
           ('Mountain Bikes', 'Silver'),
           ('Road Bikes', 'Red'),
           ('Road Bikes', 'Red'),
           ('Road Bikes', 'Red'),
           ('Road Bikes', 'Black'),
           ('Road Bikes', 'Yellow') 
  ) AS Bikes(Name, Colour)
)
SELECT
  Name, 
  COALESCE(Red, 0) AS Red, 
  COALESCE(Blue, 0) AS Blue, 
  COALESCE(Black, 0) AS Black, 
  COALESCE(Silver, 0) AS Silver, 
  COALESCE(Yellow, 0) AS Yellow, 
  COALESCE(Grey, 0) AS Grey, 
  COALESCE(Multi, 0) AS Multi, 
  COALESCE(Uncoloured, 0) AS Uncoloured, 
  Total
FROM (
  SELECT 
    Coalesce(Name, 'Total') Name, 
    COALESCE(Colour, 'Total') Colour, 
    COUNT(*) Count
  FROM Bikes
  GROUP BY CUBE (Name, Colour)
) AS t
PIVOT (
  MAX(Count) FOR Colour IN (
    Red, Blue, Black, Silver, Yellow, Grey, Multi, Uncoloured, Total
  )
) AS p
ORDER BY CASE Name WHEN 'Total' THEN 1 ELSE 0 END, Name

SQLFiddle here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-29
    • 2012-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多