Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/78.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
动态计算的SQL百分比_Sql_Intersystems Cache - Fatal编程技术网

动态计算的SQL百分比

动态计算的SQL百分比,sql,intersystems-cache,Sql,Intersystems Cache,如何在SQL中动态计算百分比 假设您有一个名为Classes的下表: ClassSession StudentName --------------------------------- Evening Ben Morning Chris Afternoon Roger Evening Ben Afternoon Ben Morning Roger Mornin

如何在SQL中动态计算百分比

假设您有一个名为
Classes
的下表:

ClassSession       StudentName
---------------------------------
Evening            Ben
Morning            Chris
Afternoon          Roger
Evening            Ben
Afternoon          Ben
Morning            Roger
Morning            Ben
Afternoon          Chris
比如说Ben,我期待着

Evening = 50 %
Afternoon = 25%
Morning = 25%
Morning = 50%
Afternoon = 50%
Evening = 0 %
我期待着克里斯的到来

Evening = 50 %
Afternoon = 25%
Morning = 25%
Morning = 50%
Afternoon = 50%
Evening = 0 %
所以
ClassSession
(三个session)在比较时应该是常量

到目前为止,我已经尝试了以下SQL语句:

Select 
    ClassSession,
    (Count(ClassSession) * 100 / (Select Count(*) From Classes)) as Percentage
From 
    Classes
Where 
    StudentName = 'Chris'
Group By 
    ClassSession

一种方法使用条件聚合和窗口函数:

Select ClassSession,
       (sum(case when StudentName = 'Chris' then 100.0 else 0 end) /
        sum(sum(case when StudentName = 'Chris' then 100.0 else 0 end)) over ()
       ) as Percentage
From Classes
Group By ClassSession;

这将确保事件中出现零。

困难的部分是让在给定课程中没有任何课程的学生出现零

这是
分区
外部联接的作业

select c.studentname, 
       s.classsession, 
       round(ratio_to_report(count(c.classsession)) 
            over ( partition by c.studentname),2) pct
from c partition by ( studentname ) 
   right outer join ( SELECT distinct classsession from c ) s 
          on s.classsession = c.classsession
group by c.studentname, s.classsession
order by c.studentname, s.classsession;
注意join中的
分区
关键字。这告诉Oracle为每个分区执行外部联接。因此,如果给定的
studentname
没有
classsession
,请为该学生添加它

此外,
ratio\u to\u report
是计算百分比的好函数

下面是一个完整的示例,其中包含数据:

with c (ClassSession, StudentName) AS ( 
SELECT 'Evening',            'Ben' FROM DUAL UNION ALL
SELECT 'Morning',            'Chris' FROM DUAL UNION ALL
SELECT 'Afternoon',          'Roger' FROM DUAL UNION ALL
SELECT 'Evening',            'Ben' FROM DUAL UNION ALL
SELECT 'Afternoon',          'Ben' FROM DUAL UNION ALL
SELECT 'Morning',            'Roger' FROM DUAL UNION ALL
SELECT 'Morning',            'Ben' FROM DUAL UNION ALL
SELECT 'Afternoon',          'Chris' FROM DUAL)
select c.studentname, 
       s.classsession, 
       round(ratio_to_report(count(c.classsession)) 
            over ( partition by c.studentname),2) pct
from c partition by ( studentname ) 
   right outer join ( SELECT distinct classsession from c ) s on s.classsession = c.classsession
group by c.studentname, s.classsession
order by c.studentname, s.classsession;


╔══════════════════════════════════════════════════════════════════╗
║ STUDENTNAME CLASSSESSION PCT                                     ║
╠══════════════════════════════════════════════════════════════════╣
║ ----------- ------------ --------------------------------------  ║
║ Ben         Afternoon                                      0.25  ║
║ Ben         Evening                                         0.5  ║
║ Ben         Morning                                        0.25  ║
║ Chris       Afternoon                                       0.5  ║
║ Chris       Evening                                           0  ║
║ Chris       Morning                                         0.5  ║
║ Roger       Afternoon                                       0.5  ║
║ Roger       Evening                                           0  ║
║ Roger       Morning                                         0.5  ║
╚══════════════════════════════════════════════════════════════════╝

下面是使用SQLServer2008及更高版本的一种比较传统的方法。(在更高版本中,可能有更方便的方法使用统计窗口功能编写此文件。)

这将返回至少一个班级的所有学生的数据,以及至少有一个学生的所有班级的数据。如果表格很大,请取消注释
where
子句以每次获取一个学生的数据

首先,测试数据:

CREATE TABLE #Test
 (
   ClassSession  varchar(20)  not null
  ,StudentName   varchar(20)  not null
 )

INSERT #Test values 
  ('Evening', 'Ben')
 ,('Morning', 'Chris')
 ,('Afternoon', 'Roger')
 ,('Evening', 'Ben')
 ,('Afternoon', 'Ben')
 ,('Morning', 'Roger')
 ,('Morning', 'Ben')
 ,('Afternoon', 'Chris')


SELECT *
 from #Test
以及查询:

WITH cteClasses
 as (--  First, get the list of classes
     SELECT distinct ClassSession
      from #Test
     )
 ,cteStudents
  as (--  Next, get a list of all students
      SELECT
         StudentName
        ,count(*) * 1.00  ClassCount
       from #Test
       --where StudenName = @StudentParameter
       group by StudentName
     )
 --  Mush them all together, and...
 SELECT
   st.StudentName
  ,cl.ClassSession
  ,count(te.StudentName) / st.ClassCount * 100  Percentage
 from cteStudents st
  cross join cteClasses cl
  left join #Test te
   on te.ClassSession = cl.ClassSession
    and te.StudentName = st.StudentName
 group by
   st.StudentName
  ,cl.ClassSession
  ,st.ClassCount
 order by 
   st.StudentName
  ,cl.ClassSession

在子查询中还需要StudentName条件。让它成为一个相关的子查询。用你正在使用的数据库标记你的问题。感谢提醒我标记了系统间缓存谢谢我,虽然数据库是带有简单SQL的系统间缓存,但你的回答给出了一个很好的方向谢谢Philip,数据库是系统间缓存,但我喜欢你的方法