在SQL中查找多列中的大多数事件

时间:2013-08-29 14:26:59

标签: sql sql-server tsql

我有一张这样的表:

Answer1,Answer2,Answer3,Answer4  
A,B,C,C  
B,D,D,D  
C,C,A,C  
B,B,D,D

我想找到所有四个答案的最多出现次数,如果出现次数相同,我只需要第一个值。理想情况下,我应该有一个这样的输出表:

Answer1,Answer2,Answer3,Answer4,MostAnswers,Occurrences  
A,B,C,C,C,2  
B,D,D,D,D,3  
C,C,A,C,C,3  
B,B,D,D,B,2

如何在sql server中执行此操作?我可以逐行进行分组吗?

2 个答案:

答案 0 :(得分:5)

另一种方法仍然假设存在Id列:

select 
  a.Id,
  a.Answer1, 
  a.Answer2, 
  a.Answer3, 
  a.Answer4,
  TopAnswers.*
from AnswerTable a
outer apply (
  select top 1 Answer, count(*) as cnt
  from (
    select Answer1 as Answer from AnswerTable where Id = a.Id
    union all
    select Answer2 from AnswerTable where Id = a.Id
    union all
    select Answer3 from AnswerTable where Id = a.Id
    union all
    select Answer4 from AnswerTable where Id = a.Id
  ) x
  group by Answer
  order by count(*) desc, Answer asc
) TopAnswers

以下是SQLFiddle:http://sqlfiddle.com/#!3/b1dfd/8

答案 1 :(得分:1)

一种方法是取消数据的转移。诀窍是你需要一个id来识别每一行。这是在以下查询中使用row_number()获得的。然后获取所需的值需要明智地使用聚合和窗口函数:

with t as (
      select (case when n.n = 1 then answer1
                   when n.n = 2 then answer2
                   when n.n = 3 then answer3
                   when n.n = 4 then answer4
              end) as answer, a.*
      from (select row_number() over (order by (select NULL)) as recnum, a.*
            from answers a
           ) cross join
           (select 1 as n union all select 2 union all select 3 union all select 4) n
    )
select answer1, answer2, answer3, answer4, answer, cnt
from (select recnum, answer1, answer2, answer3, answer4, answer, count(*) as cnt,
             row_number() over (partition by recnum order by count(*) desc
                               ) as seqnum_cnt
      from t
      group by recnum, answer1, answer2, answer3, answer4, answer
     ) a
where seqnum_cnt = 1;