3

テーブルに次の列がある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)を生成できますか?

4

1 に答える 1

10
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

作業デモ

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

作業デモ

2番目のバージョンでは、除算する前に100を掛けないことにしました。これには10進数へのキャストが必要です。そうでない場合、暗黙的にintに変換され、レコードが返されません。

また、これが必要かどうかは完全にはわかりませんが、TOP 1両方のクエリに追加すると、結果が30%を超える店舗数が最も多いものに限定されます。

アップデート

あなたのコメントに基づいて、それはケビンを言い換えるように聞こえます

従業員が最も多い店舗から始めて、少なくとも30%になるまで行が必要です。

これは、実行パーセンテージとビンパッキング問題を必要とするため困難ですが、これは機能します。他の2つのテストケースを含めたことに注意してください(パーセントが正確に等しく、上位2つを合わせたもののすぐ上にあります)

作業デモ

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       
于 2012-04-06T17:46:58.163 に答える