如何连接两个选择计数语句

时间:2017-07-31 16:40:58

标签: sql sql-server tsql

例如,如果我有一个表'studentActivities',其中每次学生进行活动时都会记录。像这样:

activity         countryofbirth    name    event_date
School Swimming  USA               Bob     5/21/2017 12:50
Park Swimming    Australia         Sarah   2/11/2017 19:50
Park Swimming    Australia         Sarah   2/13/2017 16:50
Park Running     USA               Bob     2/10/2017 11:50
School Tennis    USA               Bob     2/12/2017 11:50
NULL             USA               Jane    8/4/2016 13:30

我正在尝试根据学生In-School ActvityOut-of-School Activity来计算学生所做的不同活动。

这是4校内活动的特色: School Swimming, School Running, School Soccer, School Tennis

我想得到的是一张表:

 Student_Name Country_of_Birth In-School_Activities Out_of_School_Activities
 Bob          USA              2                    1
 Sarah        Australia        0                    1
 Jane         USA              0                    0

我试过了:

SELECT 
 studentActivities.name AS [student_name],
 studentActivities.countryofbirth AS County_of_Birth],
 COUNT (DISTINCT activity) as [In-School Activities]

 FROM studentActivities

 WHERE studentActivities.activity IN ('School Swimming', 'School Running', 'School Soccer', 'School Tennis')

 GROUP BY  studentActivities.name, studentActivities.countryofbirth

 UNION

 SELECT 
 studentActivities.name AS [student_name],
 studentActivities.countryofbirth AS [County_of_Birth],
 COUNT (DISTINCT activity) as [Out_of_School Activities]

 FROM studentActivities

 WHERE studentActivities.activity NOT IN ('School Swimming', 'School Running', 'School Soccer', 'School Tennis')

 GROUP BY  studentActivities.name, studentActivities.countryofbirth

但这并没有给我我想要的结果。我怎样才能得到我想要的结果?

8 个答案:

答案 0 :(得分:1)

您应该使用Full Outer Join

 WITH InSchool AS (
 SELECT 
 studentActivities.name AS [student_name],
 studentActivities.countryofbirth ,
 COUNT (DISTINCT activity) as [In-School Activities]
 FROM studentActivities
 WHERE studentActivities.activity IN ('School Swimming', 'School Running', 'School Soccer', 'School Tennis')
 GROUP BY  studentActivities.name, studentActivities.countryofbirth
 )
, OutOfSchool AS ( 
 SELECT 
 studentActivities.name AS [student_name],
 studentActivities.countryofbirth,
 COUNT (DISTINCT activity) as [Out_of_School Activities]
 FROM studentActivities
 WHERE studentActivities.activity NOT IN ('School Swimming', 'School Running', 'School Soccer', 'School Tennis')
 GROUP BY  studentActivities.name, studentActivities.countryofbirth
 )
 SELECT
  COALESCE(InSchool.student_name, OutOfSchool.student_name) [Student_Name],
  COALESCE(InSchool.CountryOfBirth, OutOfSchool.CountryOfBirth) CountryOfBirth,
  COALESCE(InSchool.[In-School Activities],0) [In-School Activities],
  COALESCE(OutOfSchool.[Out_of_School Activities],0) [Out_of_School Activities]
 FROM InSchool
 FULL OUTER JOIN OutOfSchool
 ON InSchool.[student_name] = OutOfSchool.[Student_name]
 AND InSchool.CountryOfBirth = OutOfSchool.CountryOfBirth

答案 1 :(得分:1)

这就是我想到的,我没有验证,但这就是我完成任务的方式

SELECT 
 name AS [student_name],
 countryofbirth AS [Manufacturer],
 sum (activity IN ('School Swimming', 'School Running', 'School Soccer', 'School Tennis')) as [In-School Activities],
 sum (activity NOT IN ('School Swimming', 'School Running', 'School Soccer', 'School Tennis')) as [Out_of_School Activities]
 FROM (select distinct studentActivities.name, studentActivities.countryofbirth, activity) x 
 GROUP BY  name, countryofbirth;

答案 2 :(得分:1)

你应该使用联接(而不是联盟)

select a.[student_name], a.[student_name],  a.[In-School Activities], b.[Out_of_School Activities]
from ( 
  SELECT 
   studentActivities.name AS [student_name],
   studentActivities.countryofbirth AS [Manufacturer],
   COUNT (DISTINCT activity) as [In-School Activities]
   FROM studentActivities
   WHERE studentActivities.activity IN ('School Swimming', 'School Running', 'School Soccer', 'School Tennis')
   GROUP BY  studentActivities.name, studentActivities.countryofbirth 
 ) a
 left  join (
   SELECT 
   studentActivities.name AS [student_name],
   studentActivities.countryofbirth AS [Manufacturer],
   COUNT (DISTINCT activity) as [Out_of_School Activities]
   FROM studentActivities
   WHERE studentActivities.activity NOT IN ('School Swimming', 'School Running', 'School Soccer', 'School Tennis')
   GROUP BY  studentActivities.name, studentActivities.countryofbirth 
 ) b on a.[student_name] = b.[student_name] and a.[Manufacturer] = b.[Manufacturer]

答案 3 :(得分:1)

我会使用Case语句:

SELECT 
 Sa.name AS [student_name],
 Sa.countryofbirth,

 Sum(Case when sa.activity IN ('School Swimming', 'School Running', 'School Soccer', 'School Tennis')
 then 1 else 0 end) as In_school_Activities,

 Sum(Case when sa.activity IN ('School Swimming', 'School Running', 'School Soccer', 'School Tennis')
 then 0 else 1 end) as Out_of_school_Activities


 FROM (select distinct student_name, country _of_birth, activity from studentActivities) sa

 GROUP BY  sa.name, sa.countryofbirth

请注意,在任何非平凡的应用程序中,名称永远不能被视为唯一。如果您有一个标识符(并且您应该随时拥有名称),那么最好对其进行分组。

答案 4 :(得分:1)

Pivot会解决这个问题。我使用您提供的数据对其进行了测试,并且按预期工作。

SELECT
    Name
    ,countryofbirth
    , [In-School Activity]
    ,[Out-of-School Activity]
FROM(
    SELECT
        name
        ,countryofbirth
        ,CASE Activity
            WHEN 'School Swimming' THEN 'In-School Activity'
            WHEN 'School Running'  THEN 'In-School Activity'
            WHEN 'School Soccer'   THEN 'In-School Activity'
            WHEN 'School Tennis'   THEN 'In-School Activity'        
            ELSE 'Out-of-School Activity'
        END class
    FROM studentactivities
    WHERE Activity IS NOT NULL
)AS base
PIVOT(
    COUNT (CLASS)
    FOR CLASS IN ([In-School Activity],[Out-of-School Activity])
)AS Pivoted

答案 5 :(得分:1)

鲍勃有2个乡村分娩地点。是2个单独的Bobs还是错误?我没有对此进行测试,因此它可能不是100%准确,但我更喜欢常见的表格表达式:

;WITH cte
AS (
SELECT DISTINCT NAME AS [student_name]
    ,countryofbirth
    ,activity
    ,CASE 
        WHEN activity IN (
                'School Swimming'
                ,'School Running'
                ,'School Soccer'
                ,'School Tennis'
                )
            THEN 1
        ELSE 0
        END AS [In-school_activity_count]
    ,CASE 
        WHEN activity IS NOT NULL
            AND activity NOT IN (
                'School Swimming'
                ,'School Running'
                ,'School Soccer'
                ,'School Tennis'
                )
            THEN 1
        ELSE 0
        END AS [Out-of-school_activity_count]
FROM studentActivities
)
SELECT student_name
,countryofbirth
,SUM([In-school_activity_count]) AS [In-School_Activities]
,SUM([Out-of-school_activity_count]) AS [Out_of_School_Activities]
FROM cte
GROUP BY student_name
,countryofbirth

答案 6 :(得分:1)

使用count(distinct ...)

的条件聚合
select 
    Name
  , CountryOfBirth
  , InSchoolActivies    = count(distinct case when activity in ('School Swimming', 'School Running', 'School Soccer', 'School Tennis') then activity end)
  , OutOfSchoolActivies = count(distinct case when activity not in ('School Swimming', 'School Running', 'School Soccer', 'School Tennis') then activity end)
from StudentActivites
group by Name, CountryOfBirth

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

返回:(在样本数据中更正Bob的出生国家后)

+-------+----------------+------------------+---------------------+
| Name  | CountryOfBirth | InSchoolActivies | OutOfSchoolActivies |
+-------+----------------+------------------+---------------------+
| Bob   | USA            |                2 |                   1 |
| Jane  | USA            |                0 |                   0 |
| Sarah | Australia      |                0 |                   1 |
+-------+----------------+------------------+---------------------+

答案 7 :(得分:1)

以下内容很简单,有效:

select name,countryofbirth,sum(schoolflag) as 
In_School_Activity,sum(nonschool) Out_Of_School_Activity
from 
 (
 select activity,name,countryofbirth,
 case when activity like 'School%' then 1 else 0 end as schoolflag ,
 case when activity not like 'School%' then 1 else 0 end as nonschool
 from schoolactivity
 )a
group by name,countryofbirth