2013-04-29 76 views
1

我有一個不尋常的情況。請考慮下面的代碼:字符字段中排名前3的值的百分比

IF OBJECT_ID('tempdb..#CharacterTest') IS NOT NULL 
    DROP TABLE #CharacterTest 

CREATE TABLE #CharacterTest 
(
    [ID] int IDENTITY(1, 1) NOT NULL, 
[CharField] varchar(50) NULL 
) 


INSERT INTO #CharacterTest (CharField) 
VALUES ('A') 
     , ('A') 
     , ('A') 
     , ('A') 
     , ('B') 
     , ('B') 
     , ('B') 
     , ('C') 
     , ('C') 
     , ('D') 
     , ('D') 
     , ('F') 
     , ('G') 
     , ('H') 
     , ('I') 
     , ('J') 
     , ('K') 
     , ('L') 
     , ('M') 
     , ('N') 
     , (' ') 
     , (' ') 
     , (' ') 
     , (NULL) 
     , (''); 

我想查詢它給了我一個字符串是這樣的: A(16%),B(12%),C(8%)

請注意以下幾點:

  • 我不希望有空字符串,字符串的所有空格,或前3列空,但我想用整個記錄計數表計算值的百分比。
  • 關係可以忽略,所以如果列表中有22個值的頻率爲8%,那麼只要返回任何一個首先就可以。
  • 百分比可以四捨五入爲整數。

我想找到最簡單的方法來編寫此查詢,同時仍然保留T-SQL兼容性回到SQL Server 2005.什麼是最好的方式來做到這一點?窗口函數?

回答

2

我會去的。

WITH T1 
    AS (SELECT [CharField], 
       100.0 * COUNT(*) OVER (PARTITION BY [CharField])/
              COUNT(*) OVER() AS Pct 
     FROM #CharacterTest), 
    T2 
    AS (SELECT DISTINCT TOP 3 * 
     FROM T1 
     WHERE [CharField] <> '' --Excludes all blank or NULL as well 
     ORDER BY Pct DESC) 
SELECT STUFF((SELECT ',' + [CharField] + ' (' + CAST(CAST(ROUND(Pct,1) AS INT) AS VARCHAR(3)) + ')' 
       FROM T2 
       ORDER BY Pct DESC 
       FOR XML PATH('')), 1, 1, '') AS Result 
+1

沒有變量,頭髮比我的盒子上的快! – 2013-04-29 20:56:35

2

我的第一次嘗試可能是這樣的。並不是說這是處理它的最好方法,但它會起作用。

DECLARE @TotalCount INT 
SELECT @TotalCount = COUNT(*) FROM #CharacterTest AS ct 

SELECT TOP(3) CharField, COUNT(*) * 1.0/@TotalCount AS OverallPercentage 
FROM #CharacterTest AS ct 
WHERE CharField IS NOT NULL AND REPLACE(CharField, ' ', '') <> '' 
GROUP BY CharField 
ORDER BY COUNT(*) desc 

DROP TABLE #CharacterTest 
2

這應該得到你所需要的字符串:

declare @output varchar(200); 

with cte as (
    select CharField 
     , (count(*) * 100)/(select count(*) from #CharacterTest) as CharPct 
     , row_number() over (order by count(*) desc, CharField) as RowNum 
    from #CharacterTest 
    where replace(CharField, ' ', '') not like '' 
    group by CharField 
) 
select @output = coalesce(@output + ', ', '') + CharField + ' (' + cast(CharPct as varchar(11)) + '%)' 
from cte 
where RowNum <= 3 
order by RowNum; 

select @output; 

-- Returns: 
-- A (16%), B (12%), C (8%) 

我想提請注意存儲在varchar(50)列單個字符,但是。