【问题标题】:SQL query to select percentage of totalSQL查询以选择总数的百分比
【发布时间】:2012-04-06 17:38:08
【问题描述】:

我有一个 MSSQL 表存储,表中有以下列:

Storeid, NumEmployees
1       125 
2       154
3       10 
4       698
5       54  
6       98
7       87
8       100
9       58
10      897

有人可以帮助我使用 SQL 查询来生成占员工总数 (NumEmployees) 30% 的顶级商店 (storeID) 吗?

【问题讨论】:

  • 我已经尝试选择 SUM(numemploees).. 找到 30% 然后从该总和中选择顶部。
  • 我对你想要什么感到有点困惑。你想要这些行,从 storeid 1 开始一直到你总共得到 30% 吗?这将为您提供商店 1、2、3、4。还是您想要排成一行,从员工最多的商店开始,一直到有 30% 为止?哪个只会给你商店 10?或者所有拥有 30% 或更多的商店?这会给你 4 和 10。

标签: sql sql-server


【解决方案1】:
WITH cte 
     AS (SELECT storeid, 
                numemployees, 
                ( numemployees * 100 ) / SUM(numemployees) OVER (PARTITION BY 1) 
                AS 
                percentofstores 
         FROM   stores) 
SELECT * 
FROM   cte 
WHERE  percentofstores >= 30 
ORDER BY numemployees desc

Working Demo

不使用 SUM/OVER 的替代方案

SELECT s.storeid, s.numemployees 
FROM   (SELECT SUM(numemployees) AS [tots] 
        FROM   stores) AS t, 
       stores s 
WHERE  CAST(numemployees AS DECIMAL(15, 5)) / tots >= .3 
ORDER BY s.numemployees desc

Working Demo

请注意,在第二个版本中,我决定在除之前不乘以 100。这需要强制转换为十进制,否则它将被隐式转换为 int 导致不返回任何记录

另外,我不完全清楚您是否想要这个,但您可以将 TOP 1 添加到两个查询中,这会将结果限制为具有最多商店数量且超过 30% 的结果

更新

根据您的 cmets,听起来可以解释为 Kevin

你想要这些行,从员工最多的商店开始,一直到至少有 30% 的商店

这很困难,因为它需要一个运行百分比和一个装箱问题,但这确实有效。请注意,我已经包含了另外两个测试用例(其中百分比完全等于并且刚好超过前两个的总和)

Working Demo

DECLARE @percent DECIMAL (20, 16) 

SET @percent = 0.3
--Other test values
--SET @percent = 0.6992547128452433
--SET @percent = 0.6992547128452434 

;WITH sums 
     AS (SELECT DISTINCT s.storeid, 
                         s.numemployees, 
                         s.numemployees + Coalesce(SUM(s2.numemployees) OVER ( 
                                                   PARTITION 
                                                   BY 
                                                   s.numemployees), 0) 
                         runningsum 
         FROM   stores s 
                LEFT JOIN stores s2 
                  ON s.numemployees < s2.numemployees), 
     percents 
     AS (SELECT storeid, 
                numemployees, 
                runningsum, 
                CAST(runningsum AS DECIMAL(15, 5)) / tots.total 
                running_percent, 
                Row_number() OVER (ORDER BY runningsum, storeid ) rn 
         FROM   sums, 
                (SELECT SUM(numemployees) total 
                 FROM   stores) AS tots) 
SELECT p.storeID,
       p.numemployees,
       p.running_percent,
       p.running_percent,
       p.rn 
FROM   percents p 
       CROSS JOIN (SELECT MAX(rn) rn 
                  FROM   percents 
                  WHERE  running_percent = @percent) exactpercent 

       LEFT JOIN (SELECT MAX(rn) rn 
                   FROM   percents 
                   WHERE  running_percent <= @percent) underpercent 
         ON p.rn <= underpercent.rn 
             OR ( exactpercent.rn IS NULL 
                  AND p.rn <= underpercent.rn + 1 ) 
WHERE 
      underpercent.rn is not null or p.rn = 1       

【讨论】:

  • 这不起作用。内部查询不会产生 0 from percentofstores
  • 我的意思是。内部查询生成 0 作为每条记录的 percentofstores 的结果
  • hmm 你在除法前删除了* 100 吗?如果你这样做了,你需要转换为十进制
  • 如果您自己创建了一个 SQL Fiddle 来证明它会更容易提供帮助?
  • 我通过 hack 找到了答案。 B = Sum(numemplyees(. select top N Isrc from table order by numemployees desc 所以我不断改变 N 直到 sum = B
猜你喜欢
  • 2016-04-09
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 2017-03-22
  • 1970-01-01
  • 2021-10-26
  • 1970-01-01
  • 2013-11-17
相关资源
最近更新 更多