Supposons que j'ai un tableau avec une colonne numérique (appelons-le "score").
J'aimerais générer un tableau de comptes indiquant le nombre de fois où des scores sont apparus dans chaque plage.
Par exemple:
plage de scores | nombre d'occurrences ------------------------------------- 0-9 | 11 10-19 | 14 20-29 | 3 ... | ...
Dans cet exemple, il y avait 11 lignes avec des scores allant de 0 à 9, 14 lignes avec des scores de 10 à 19 et 3 lignes avec des scores de 20 à 29.
Y a-t-il un moyen facile de le configurer? Que recommandez-vous?
Aucune des réponses les plus votées n'est correcte sur SQLServer 2000. Ils utilisaient peut-être une version différente.
Voici les versions correctes des deux sur SQLServer 2000.
select t.range as [score range], count(*) as [number of occurences]
from (
select case
when score between 0 and 9 then ' 0- 9'
when score between 10 and 19 then '10-19'
else '20-99' end as range
from scores) t
group by t.range
ou
select t.range as [score range], count(*) as [number of occurences]
from (
select user_id,
case when score >= 0 and score< 10 then '0-9'
when score >= 10 and score< 20 then '10-19'
else '20-99' end as range
from scores) t
group by t.range
Une approche alternative consisterait à stocker les plages dans une table, au lieu de les incorporer dans la requête. Vous vous retrouveriez avec une table, appelez-la Ranges, qui ressemble à ceci:
LowerLimit UpperLimit Range
0 9 '0-9'
10 19 '10-19'
20 29 '20-29'
30 39 '30-39'
Et une requête qui ressemble à ceci:
Select
Range as [Score Range],
Count(*) as [Number of Occurences]
from
Ranges r inner join Scores s on s.Score between r.LowerLimit and r.UpperLimit
group by Range
Cela signifie qu’il faut mettre en place une table, mais il serait facile à maintenir lorsque les plages souhaitées changent. Aucun changement de code nécessaire!
Je vois ici des réponses qui ne fonctionneront pas dans la syntaxe de SQL Server. J'utiliserais:
select t.range as [score range], count(*) as [number of occurences]
from (
select case
when score between 0 and 9 then ' 0-9 '
when score between 10 and 19 then '10-19'
when score between 20 and 29 then '20-29'
...
else '90-99' end as range
from scores) t
group by t.range
EDIT: voir les commentaires
En postgres (où ||
est l'opérateur de concaténation de chaînes):
select (score/10)*10 || '-' || (score/10)*10+9 as scorerange, count(*)
from scores
group by score/10
order by 1
donne:
scorerange | count
------------+-------
0-9 | 11
10-19 | 14
20-29 | 3
30-39 | 2
La réponse de James Curran était la plus concise à mon avis, mais le résultat n'était pas correct. Pour SQL Server, l’instruction la plus simple est la suivante:
SELECT
[score range] = CAST((Score/10)*10 AS VARCHAR) + ' - ' + CAST((Score/10)*10+9 AS VARCHAR),
[number of occurrences] = COUNT(*)
FROM #Scores
GROUP BY Score/10
ORDER BY Score/10
Cela suppose une table temporaire #Scores que j'ai utilisée pour la tester. Je viens de remplir 100 lignes avec un nombre aléatoire compris entre 0 et 99.
create table scores (
user_id int,
score int
)
select t.range as [score range], count(*) as [number of occurences]
from (
select user_id,
case when score >= 0 and score < 10 then '0-9'
case when score >= 10 and score < 20 then '10-19'
...
else '90-99' as range
from scores) t
group by t.range
select cast(score/10 as varchar) + '-' + cast(score/10+9 as varchar),
count(*)
from scores
group by score/10
Cela vous permettra de ne pas avoir à spécifier de plages et devrait être agnostique pour SQL Server. Math FTW!
SELECT CONCAT(range,'-',range+9), COUNT(range)
FROM (
SELECT
score - (score % 10) as range
FROM scores
)
Je le ferais un peu différemment pour qu'il évolue sans avoir à définir chaque cas:
select t.range as [score range], count(*) as [number of occurences]
from (
select FLOOR(score/10) as range
from scores) t
group by t.range
Non testé, mais vous avez l'idée ...
declare @RangeWidth int
set @RangeWidth = 10
select
Floor(Score/@RangeWidth) as LowerBound,
Floor(Score/@RangeWidth)+@RangeWidth as UpperBound,
Count(*)
From
ScoreTable
group by
Floor(Score/@RangeWidth)
Comme la colonne en cours de tri (Range
) est une chaîne, le tri chaîne/mot est utilisé à la place du tri numérique.
Tant que les chaînes ont des zéros pour compléter les longueurs de nombres, le tri doit toujours être correct sémantiquement:
SELECT t.range AS ScoreRange,
COUNT(*) AS NumberOfOccurrences
FROM (SELECT CASE
WHEN score BETWEEN 0 AND 9 THEN '00-09'
WHEN score BETWEEN 10 AND 19 THEN '10-19'
ELSE '20-99'
END AS Range
FROM Scores) t
GROUP BY t.Range
Si la plage est mélangée, il suffit de remplir un zéro supplémentaire:
SELECT t.range AS ScoreRange,
COUNT(*) AS NumberOfOccurrences
FROM (SELECT CASE
WHEN score BETWEEN 0 AND 9 THEN '000-009'
WHEN score BETWEEN 10 AND 19 THEN '010-019'
WHEN score BETWEEN 20 AND 99 THEN '020-099'
ELSE '100-999'
END AS Range
FROM Scores) t
GROUP BY t.Range
Essayer
SELECT (str(range) + "-" + str(range + 9) ) AS [Score range], COUNT(score) AS [number of occurances]
FROM (SELECT score, int(score / 10 ) * 10 AS range FROM scoredata )
GROUP BY range;
select t.blah as [score range], count(*) as [number of occurences]
from (
select case
when score between 0 and 9 then ' 0-9 '
when score between 10 and 19 then '10-19'
when score between 20 and 29 then '20-29'
...
else '90-99' end as blah
from scores) t
group by t.blah
Assurez-vous que vous utilisez un mot autre que "range" si vous êtes dans MySQL, sinon vous obtiendrez une erreur en exécutant l'exemple ci-dessus.