【问题标题】:Adding percentages to multiple counts in one SQL SELECT Query在一个 SQL SELECT 查询中向多个计数添加百分比
【发布时间】:2009-10-05 17:29:50
【问题描述】:

我有一个类似于下面的 SELECT 语句,它在一个查询中返回多个计数。

SELECT  invalidCount = (SELECT COUNT(*) FROM <...a...> WHERE <...b...>),
        unknownCount = (SELECT COUNT(*) FROM <...c...> WHERE <...d...>),
        totalCount   = (SELECT COUNT(*) FROM <...e...> WHERE <...f...>)

这很好用,但我想在 SELECT 中添加两个百分比列:

invalidCount * 100 / totalCount AS PercentageInvalid, 
unknownCount * 100 / totalCount AS UnknownPercentage

如何修改我的 SELECT 语句来处理这个问题?

【问题讨论】:

    标签: sql sql-server sql-server-2005


    【解决方案1】:

    您可以在from 子句中使用子查询:

    select
        s.invalidCount,
        s.unknownCount,
        s.totalCount,
        invalidCount * 100 / s.totalCount as PercentageInvalid,
        unknownCount * 100 / s.totalCount as PercentageUnknown
    from
        (select  invalidCount = (SELECT COUNT(*) FROM <...a...> WHERE <...b...>),
            unknownCount = (SELECT COUNT(*) FROM <...c...> WHERE <...d...>),
            totalCount       = (SELECT COUNT(*) FROM <...e...> WHERE <...f...>)) s
    

    【讨论】:

      【解决方案2】:
      SELECT invalidCount, 
        unknownCount, 
        totalCount, 
        invalidCount * 100 / totalCount AS PercentageInvalid, 
        unknownCount * 100 / totalCount AS UnknownPercentage 
      FROM 
          (
            SELECT  invalidCount = (SELECT COUNT(*) FROM <...a...> WHERE <...b...>),  
            unknownCount = (SELECT COUNT(*) FROM <...c...> WHERE <...d...>),     
            totalCount       = (SELECT COUNT(*) FROM <...e...> WHERE <...f...>)
          )
      

      【讨论】:

      • 不要忘记 CAST(totalCount as float) - 否则你正在做整数除法......
      【解决方案3】:

      这是一种使用 OVER 子句的不同方法,非常酷 - 非常有效。看看这个针对 AdventureWorks 的示例:

      SELECT DISTINCT CardType 
              ,COUNT(*) OVER (PARTITION BY CardType) AS TypeCount
              ,COUNT(*) OVER (PARTITION BY 1) AS TotalCount
              ,COUNT(*) OVER (PARTITION BY CardType) / CAST(COUNT(*) OVER (PARTITION BY 1) AS float) AS TypePercent
      FROM Sales.CreditCard
      

      【讨论】:

        【解决方案4】:

        我肯定会选择 Mike 的解决方案!更加优雅和高效。

        但我看不出有什么理由不在这里使用 GROUP BY。这将使它更加优雅和高效。我建议去掉多余的“COUNT(*) OVER (PARTITION BY 1)”,而是对计数求和。

        SELECT CardType 
               , COUNT(*) AS TypeCount
               , SUM(COUNT(*)) OVER () AS TotalCount
               , COUNT(*) * 1.0 / SUM(COUNT(*)) OVER () AS TypePercent
        FROM Sales.CreditCard
        GROUP BY CardType
        

        注意事项:

        • “PARTITION BY 1”是多余的,因此省略。
        • 计算 CardType-Counts 的 SUM 我们从数整张桌子一次 再次不分区。
        • 使用*1.0 代替强制转换。
        • 查询未测试,但应该可以工作..

        【讨论】:

          【解决方案5】:
          SELECT  invalidCount = (SELECT COUNT(*) FROM <...a...> WHERE <...b...>),
                  unknownCount = (SELECT COUNT(*) FROM <...c...> WHERE <...d...>),
                  totalCount       = (SELECT COUNT(*) FROM <...e...> WHERE <...f...>)
          INTO #tmp
          
          SELECT invalidCount,
                 unknownCount,
                 totalCount,
                 invalidCount * 100 / totalCount AS PercentageInvalid, 
                 unknownCount * 100 / totalCount AS UnknownPercentage
          FROM #tmp
          
          DROP TABLE #tmp
          

          【讨论】:

          • 这比“从(现有查询)中选择无效计数*100(等)”更快吗
          • 不确定witch 是否更快,但您始终可以编写两个查询并运行并查看witch 使用SQL Profiler 是否更快
          猜你喜欢
          • 2013-03-16
          • 1970-01-01
          • 1970-01-01
          • 2021-07-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多