sql - 如何获得sql中每个答案的百分比?

标签 sql sql-server t-sql

enter image description here

我有一个民意调查系统。我使用此查询来获取问题的每个答案的计数。我怎样才能获得每个回答选项的百分比,如下所示:

question 1 ---> option1=20.13 % ---> option2=79.87 %

question 2 ---> option3=100 %

question 3 ---> option4=30 % ---> option5=70 %

....

我尝试了这个查询,但这不是我的愿望:

[getPollResult]

@poll_form_id int

AS
BEGIN

SELECT a.question_id,a.title,COUNT(*) vote 
FROM tbl_poll_option a 
  JOIN tbl_poll_answer b ON a.Id=b.option_id
  JOIN tbl_poll_question c ON a.question_id=c.Id
WHERE poll_form_id=@poll_form_id 
GROUP BY a.title,a.question_id

END

最佳答案

我同意在前端进行计算(如百分比)的建议。

话虽如此,这可能对您有帮助。
设计限制:这适用于相对较小的数据集,我发现“with()”语法比制作临时表更容易使用,并希望我记得清理它们。 (有关“with...as..”sytnax see here 的更多信息)。

以下sql(未经测试)尝试生成两个临时结果集。

counts_by_option - # of votes for each question+option pair
counts_by_question - total # of votes for each question

让我们慢慢来:

按选项计数

这或多或少是你开始的内容(实际上只是多一点,我想我们稍后可能想知道问题和选项,所以我们现在捕获它们):

with counts_by_option( question_id, question_title, option_id, option_title, vote_cnt )
as (
   SELECT opt.question_id
        , quest.title as question_title
        , opt.id as option_id
        , opt.title as option_title
        , COUNT(*) vote_cnt
   FROM tbl_poll_option opt
   JOIN tbl_poll_answer ans     ON ans.option_id = opt.Id
   JOIN tbl_poll_question quest ON quest.Id = opt.question_id
   WHERE poll_form_id=@poll_form_id
   GROUP BY opt.question_id, quest.title, opt.id, opt.title
)
select * from counts_by_option
order by question_id, option_id

如果可行,让我们扩展 sql 并添加下一个临时结果集...

按问题计数

现在我们可以使用选项总计来生成每个问题的总票数;稍后我们将需要它来计算实际的 %ge。

with counts_by_option( question_id, question_title, option_id, option_title, vote_cnt )
as (
   SELECT opt.question_id
        , quest.title as question_title
        , opt.id as option_id
        , opt.title as option_title
        , COUNT(*) vote_cnt
   FROM tbl_poll_option opt
   JOIN tbl_poll_answer ans     ON ans.option_id = opt.Id
   JOIN tbl_poll_question quest ON quest.Id = opt.question_id
   WHERE poll_form_id=@poll_form_id
   GROUP BY opt.question_id, quest.title, opt.id, opt.title
)
-- select * from counts_by_option order by question_id, option_id
-- (I like to comment out select but leave in place for future testing...)
, counts_by_question( question_id, question_total_votes )
as (
   select question_id, sum(vote_cnt) as question_total_votes 
   from counts_by_option group by question_id
)
select * from counts_by_question order by question_id

如果这有效,我们(最终)就能回答有关百分比的原始问题:

百分比示例

with counts_by_option( question_id, question_title, option_id, option_title, vote_cnt )
as (
   SELECT opt.question_id
        , quest.title as question_title
        , opt.id as option_id
        , opt.title as option_title
        , COUNT(*) vote_cnt
   FROM tbl_poll_option opt
   JOIN tbl_poll_answer ans     ON ans.option_id = opt.Id
   JOIN tbl_poll_question quest ON quest.Id = opt.question_id
   WHERE poll_form_id=@poll_form_id
   GROUP BY opt.question_id, quest.title, opt.id, opt.title
)
-- select * from counts_by_option order by question_id, option_id
-- (I like to comment out select but leave in place for future testing...)
, counts_by_question( question_id, question_total_votes )
as (
   select question_id, sum(vote_cnt) as question_total_votes 
   from counts_by_option group by question_id
)
-- select * from counts_by_question order by question_id
select question_id
     , question_title
     , option_id
     , option_title
     , vote_cnt
     , (100.0 * vote_cnt)
       / (select b.question_total_votes
          from counts_by_question b
          where b.question_id = a.question_id
         ) as option_percentage
from counts_by_option a
order by question_id, vote_cnt desc

结果集由counts_by_option a驱动。
百分比表达式向counts_by_question b寻求帮助。

让我们关注option_percentage的表达式:

(100.0 * vote_cnt)
/ (select b.question_total_votes
   from counts_by_question b
   where b.question_id = a.question_id
)
as option_percentage

这有点复杂(这就是为什么我更喜欢在前端做聚合之类的事情),但还不错......

我们首先将 vote_count 乘以 100.0
然后,我们使用当前的 OPTION 来驱动子查询,该子查询命中 Question_total_values 来查找当前问题的总票数。
请注意限定符 ab,这对于将我们针对 counts_by_question 的子查询仅集中在 a 上非常重要使用此 where 子句的当前问题:where b.question_id = a.question_id(很重要,因为这样的子查询只能返回单个值,否则会在执行时出错)。

如果任何问题的总票数为零(例如除以零错误),这就会爆炸。
编辑:counts_by_option的构建方式,仅使用带有答案的问题(表tbl_poll_answer),因此counts_by_question中的所有值b> 将非零。

关于sql - 如何获得sql中每个答案的百分比?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35356053/

相关文章:

SQL:了解这两个查询之间的区别

MySQL datetime where 子句查询帮助

sql - 使用knex对3张表进行join操作

mysql - 按期间分组结果

sql-server - SQL Server 递归路径 ID

sql-server - 计算 SQL Server Round Up 中两个日期之间的周数

SQL查询以获得满足条件的直接父级

php - MYSQL插入记录花费太多时间

sql-server - 对以下数据进行透视/逆透视

sql-server - 无法找到任一列 "dbo"或用户定义函数无法找到任一列