2014-05-16 78 views
2

我想弄清楚如何在SQL Server中實現10%45%45%分割。我想出了使用方法NTile分配一個組,然後拆分組根據簡單的數學,但是當小於20點的記錄標識如何在SQL Server中實現10%45%45%分割

SELECT 
    Email, 
    CASE 
     WHEN Group in (1,2) THEN 'Group1' 
     WHEN Group BETWEEN 3 AND 11 THEN 'Group2' 
     WHEN Group BETWEEN 12 AND 20 THEN 'Group3' 
    END AS [Group] 
FROM 
    (SELECT 
     email, optDate, 
     NTILE(20) OVER(ORDER BY NEWID()) As Group) T 

我也有不被惱人的問題的解決方案倒下能夠使用臨時表或創建變量,我的解決方案必須以選擇語句開始。我可以分階段創建結果步驟,並在階段2的查詢中使用階段1的結果,但我很難提出一個好的解決方案。

回答

2

我的方法使用明確的統計和數字這些問題。以下使用newid()隨機分配一個數字序列。剩下的只是算術:

SELECT Email, 
     (CASE WHEN seqnum <= cnt * 0.10 THEN 'Group1' 
      WHEN seqnum <= cnt * (0.10 + 0.45) THEN 'Group2' 
      ELSE 'Group3' 
     END) as [Group] 
FROM (SELECT email, optDate, 
      row_number() over (order by newid()) as seqnum, 
      count(*) over() as cnt 
     FROM t 
    ) t; 

作爲一個說明:有一些討論,指出checksum(newid())是隨機排序不僅僅是newid()其實更好。 (甚至其他人推薦rand(checksum(newid())))。出於您的目的,任何這些可能都足夠。

+0

不錯的解決方案!我認爲你有一個錯字,意思是在0.05引用的兩個地方有0.10而不是0.05。 – BateTech

+0

@BateTech。 。 。謝謝你的發現。 –

2

Row_Number應該足夠

WITH A AS (
    SELECT TOP 1000000 
     email, optDate 
     , ID = Row_Number() OVER (ORDER BY email, optDate) 
     , Items = COUNT() OVER (PARTITION BY (Select 1)) 
    FROM myTable 
    ORDER BY NEWID() 
) 
SELECT 
    Email, 
    CASE 
     WHEN ID < Items * 0.1 THEN 'Group1' 
     WHEN ID < Items * 0.55 THEN 'Group2' 
     ELSE 'Group3' 
    END AS [Group] 
FROM A 

CASE的乘數一定要添加低於當前一個以得到正確的結果(第二組從項目那張組的值* 0.10項* 0.55,差別是Items * 0.45)。

TOPCTE是必要的,以獲得ORDER BY,因爲TOP 100%不會實際結果集命令你必須使用一個號碼至少等於該查詢返回的行數。

如果您無法使用甚至CTE s的具有相同定義的子查詢替換一個主查詢:

SELECT 
    Email, 
    CASE 
     WHEN ID < Items * 0.1 THEN 'Group1' 
     WHEN ID < Items * 0.55 THEN 'Group2' 
     ELSE 'Group3' 
    END AS [Group] 
FROM (SELECT TOP 1000000 
      email, optDate 
      , ID = Row_Number() OVER (ORDER BY email, optDate) 
      , Items = COUNT() OVER (PARTITION BY (Select 1)) 
     FROM myTable 
     ORDER BY NEWID() 
    ) A