【问题标题】:Calculate totals in product matrix计算产品矩阵中的总计
【发布时间】:2015-05-26 19:06:46
【问题描述】:

假设我经营一家杂货店并希望了解我的产品的受欢迎程度。 如何从fruit 表中获取每个产品的总计,其中1 表示订单中存在产品,null 表示不存在。

order | apples | oranges | kiwis
================================
    1 |      1 |       1 | 
    2 |        |       1 | 
    3 |        |       1 |     1
    4 |      1 |         |     1
    5 |      1 |       1 |     1

我追求的结果是:

apples:  3
oranges: 4
kiwis:   3

到目前为止我已经尝试过:

select count(*) from fruit where apples  = '1'
union
select count(*) from fruit where oranges = '1'
union
select count(*) from fruit where kiwis   = '1'

这可行,但我不知道哪一行对应于哪个产品。

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    您可以使用UNPIVOT 将您的列转换为行,它们计算每个水果的行数:

    SELECT  upvt.FruitName,
            [Count] = COUNT(*)
    FROM    fruit AS f
            UNPIVOT
            (   HasFruit
                FOR FruitName IN ([Apples], [Oranges], [Kiwis])
            ) AS upvt
    GROUP BY upvt.FruitName;
    

    如果你删除聚合函数,你可以看到 unpivot 正在做什么,下面的查询:

    SELECT  upvt.*
    FROM    (VALUES
                (1,1,1,NULL),
                (2,NULL,1,NULL),
                (3,NULL,1,1),
                (4,1,NULL,1),
                (5,1,1,1)
            ) AS f ([Order], apples, oranges, Kiwis)
            UNPIVOT
            (   HasFruit
                FOR FruitName IN ([Apples], [Oranges], [Kiwis])
            ) AS upvt;
    

    将产生:

    Order   HasFruit    FruitName
    ------------------------------
    1       1           apples
    1       1           oranges
    2       1           oranges
    3       1           oranges
    3       1           Kiwis
    4       1           apples
    4       1           Kiwis
    5       1           apples
    5       1           oranges
    5       1           Kiwis
    

    然后它只是一个简单的分组和计数来获得你想要的结果。如果您还可以使用0 表示列不存在,则将您的计数更改为COUNT(NULLIF(upvt.HasFruit, 0))

    【讨论】:

    • 感谢 Gareth 提供的高级解决方案。对于我有限的 SQL 专业知识来说可能太高级了,但UNPIVOT 肯定会在以后的场景中派上用场。
    【解决方案2】:

    添加一个额外的列来标识产品:

    select 'apples' as productName, count(*) from fruit where apples  = '1'
    union
    select 'oranges', count(*) from fruit where oranges = '1'
    union
    select 'kiwis', count(*) from fruit where kiwis   = '1'
    

    【讨论】:

      猜你喜欢
      • 2015-06-23
      • 2015-07-05
      • 2023-03-09
      • 1970-01-01
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多