J'ai besoin d'une approche de classement T-SQL similaire à celle fournie par NTILE(), sauf que les membres de chaque tuile seraient sur une distribution glissante de sorte que les tuiles de rang supérieur ont moins de membres.
Par exemple
CREATE TABLE #Rank_Table(
id int identity(1,1) not null,
hits bigint not null default 0,
PERCENTILE smallint null
)
--Slant the distribution of the data
INSERT INTO #Rank_Table (hits)
select CASE
when DATA > 9500 THEN DATA*30
WHEN data > 8000 THEN DATA*5
WHEN data < 7000 THEN DATA/3 +1
ELSE DATA
END
FROM
(select top 10000 (ABS(CHECKSUM(NewId())) % 99 +1) * (ABS(CHECKSUM(NewId())) % 99 +1 ) DATA
from master..spt_values t1
cross JOIN master..spt_values t2) exponential
Declare @hitsPerGroup as bigint
Declare @numGroups as smallint
set @numGroups=100
select @hitsPerGroup=SUM(hits)/(@numGroups -1) FROM #Rank_Table
select @hitsPerGroup HITS_PER_GROUP
--This is an even distribution
SELECT id,HITS, NTILE(@numGroups) Over (Order By HITS DESC) PERCENTILE
FROM #Rank_Table
GROUP by id, HITS
--This is my best attempt, but it skips groups because of the erratic distribution
select
T1.ID,
T1.hits,
T.RunningTotal/@hitsPerGroup + 1 TILE,
T.RunningTotal
FROM #Rank_Table T1
CROSS APPLY ( Select SUM(hits) RunningTotal FROM #Rank_Table where hits <= T1.hits) T
order by T1.hits
DROP TABLE #Rank_Table
Dans #Rank_table, NTILE(@numGroups) crée une distribution égale des groupes @numGroups. Ce dont j'ai besoin, ce sont des groupes @numGroups où la tuile 1 a le moins de membres, la tuile 2 en aurait un ou plus que la tuile 1, la tuile 3 en aurait un ou plus que la tuile 2 ... la tuile 100 en aurait le plus.
J'utilise SQL Server 2008. En pratique, cette opération sera exécutée sur une table permanente comportant potentiellement des millions de lignes afin de mettre à jour périodiquement la colonne PERCENTILE avec son percentile de 1 à 100.
Ma meilleure tentative ci-dessus saute les percentiles et donne de mauvais résultats. Il doit y avoir un meilleur moyen.