首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于server中年龄组的最高计数数

基于server中年龄组的最高计数数
EN

Stack Overflow用户
提问于 2017-03-20 14:43:41
回答 3查看 521关注 0票数 2

我有两张桌子:技术人员和成员。成员只能拥有一项技术(他/她最喜欢的技术项目)。

代码语言:javascript
复制
techs: techid,tname
members: memberid,age,techcode

样本数据现在(用于技术人员):

代码语言:javascript
复制
techid    tname
  1        Mobile
  2        XBox

成员:

代码语言:javascript
复制
memberid   age   techcode
  1         8     1
  2         18    1
  3         11    2
  4         42    1

它还在继续……

现在,第一个令人感兴趣的报告/查询是获取每个年龄组每个技术项目的总受欢迎程度。因此,下面的查询做得很好。

代码语言:javascript
复制
select tname, '0-10' = count(case when age<=10 then 1 end)
,'11-20' = count(case when age BETWEEN 11 AND 20 then 1 end)
,'21-30' = count(case when age BETWEEN 21 AND 30 then 1 end)
,'31-40' = count(case when age BETWEEN 31 AND 40 then 1 end)
,'41-50' = count(case when age BETWEEN 41 AND 50 then 1 end)
,'51-60' = count(case when age BETWEEN 51 AND 60 then 1 end)
,'61-70' = count(case when age BETWEEN 61 AND 70 then 1 end)
,'71-80' = count(case when age BETWEEN 71 AND 80 then 1 end)
,'81-90' = count(case when age BETWEEN 81 AND 90 then 1 end)
,'91-100' = count(case when age BETWEEN 91 AND 100 then 1 end)
,'100+' = count(case when age >100 then 1 end)
from members,techs WHERE techcode=techid GROUP BY tname

我想要的下一个报告是按年龄组列出最受欢迎的项目。例如,当前的输出是:

代码语言:javascript
复制
tname    0-10  11-20

Mobile   7     1
XBox     4     20

我想要的下一个输出是移动最受欢迎的0-10,XBox在11-20年前很受欢迎。我现在想要的输出大致是:

代码语言:javascript
复制
Age    Highest     Tech

0-10   7         Mobile
11-20  20        Xbox

我现在没有真正的疑问。我试图对每个年龄范围执行MAX(),但是失败了,因为聚合不能超过聚合。我有点不知所措如何绕过它,所以没有真正的查询尝试显示。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-03-20 15:31:08

这是使用带有公共表表达式row_number()的另一种方法,但也使用带有表值构造函数公共表表达式而不是case表达式。

代码语言:javascript
复制
;with AgeGroup as (
  select *
  from (values 
      (0 ,10 ,'0-10')
    , (11,20,'11-20')
    , (21,30,'21-30')
    , (31,40,'31-40')
    , (41,50,'41-50')
    , (51,60,'51-60')
    , (61,70,'61-70')
    , (71,80,'71-80')
    , (81,90,'81-90')
    , (91,100,'91-100')
    , (100,null,'100+')
      ) as t(ageMin,ageMax,AgeGroup)
)
, cte as (
select
    AgeGroup
  , Highest = count(*)
  , Tech = tname
  , rn = row_number() over (
      partition by ageGroup
      order by count(*) desc
      )
from AgeGroup ag
  inner join members m 
    on m.age >= ag.ageMin
   and m.age <= ag.ageMax
  inner join techs t
    on m.techcode = t.techid
group by AgeGroup, tname
)
select ageGroup, Highest, Tech
from cte
where rn = 1

rextester演示:http://rextester.com/KMASZX6347

如果要显示没有数据的年龄组,可以将inner joins更改为left joins。

票数 0
EN

Stack Overflow用户

发布于 2017-03-20 15:13:51

您需要同时按两个维度(行而不是列)进行聚合。然后使用row_number()获取最常用的值:

代码语言:javascript
复制
select ta.*
from (select tname, agegrp, count(*) as cnt,
             row_number() over (partition by agegrp order by count(*) desc) as seqnum
      from members m join
           techs t 
           on m.techcode = t.techid cross join
           (values (case when age <= 10 then  '0-10'
                         when age <= 20 then '11-20'
                         . . .
                    end)
           ) v(agegrp)
      group by tname, agegrp
     ) ta
  where seqnum = 1;

备注:

  • 不要在FROM子句中使用逗号。始终使用正确、显式的JOIN语法。
  • cross apply为为表达式分配别名提供了一种方便的方法。
  • 您想要得到的值称为mode
票数 0
EN

Stack Overflow用户

发布于 2017-03-20 15:57:47

使用RANK() OVERUNION可以获得您想要的结果:

代码语言:javascript
复制
SELECT TOP 1 Age, Total, RANK() OVER (ORDER BY Total DESC) AS RankByTotal, Tech
        FROM(


        SELECT '0-10' Age,
        sum(A.[0-10]) Total
        ,Tech
         FROM(
                SELECT tname, Tech
                ,'0-10'  = COUNT(case when age  between 0 and 10 then 1 end) 
                FROM members m
                LEFT JOIN techs t on techcode= techid
                Group by tname, Tech) A
         Group by Tech ) B

UNION ALL 

SELECT TOP 1 Age, Total,    RANK() OVER (ORDER BY Total DESC) AS RankByTotal, Tech
        FROM(

            SELECT '11-20' Age,
            sum(A.[11-20]) Total
            ,Tech
             FROM(
                SELECT tname, Tech 
                ,'11-20' = COUNT(case when age between 11 and 20 then 1 end)
                FROM members m
                LEFT JOIN techs t on techcode= techid
                Group by tname, Tech) A
         Group by Tech) B

这种方法意味着每个年龄组都有一个UNION,这可能不是一个理想的方法。然而,它是有效的!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42906568

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档