SQL query to select percentage of total

sql, sql-server

Solution

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

Alternative that doesn't use 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

Note that in the second version I decided not to multiply by 100 before dividing. This requires a cast to decimal otherwise it would be implicitly converted to a int resulting in no records returned

Also I'm not completely clear that you want this, but you can add `TOP 1` to both queries and it will limit the results to just the one with the greatest # of stores with more than 30%

UPDATE

Based on your comments it sounds to paraphrase Kevin

You want the rows, starting at the store with the most employees and working down until you have at least 30 %

This is difficult because it requires a running percentage and its a bin packing problem however this does work. Note I've included two other test cases (where the percent exactly equals and its just over the top two combined)

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       

Problem

I have a MSSQL table stores that has the following columns in a table: ``` Storeid, NumEmployees 1 125 2 154 3 10 4 698 5 54 6 98 7 87 8 100 9 58 10 897 ``` Can someone help me with the SQL query to produce the top stores(storeID) that has 30% of the total emplyees(NumEmployees)?

Original source