使用子查询计数和groupby

时间:2017-01-20 04:32:03

标签: sql sql-server

以下是ERD

enter image description here

我想计算每个月的性别数量('男性'女性'),不论年份。

我到目前为止所尝试的是,我可以分别计算每个月的男性和女性人数,如下所示

查询

Select u.Gender, datename(month, p.EntryDate) month, COUNT(p.User_Id) count 
    from [HospitalManagement].[dbo].[Patients] p,[HospitalManagement].[dbo].[Users] u 
    where u.Id = p.User_Id 
    group by datename(month, p.EntryDate), u.Gender

结果

enter image description here

我想要它如下

预期结果

Month    | MaleCount | FemaleCount
June     |     0     |      2
November |     1     |      1

要实现上述目标,请尝试以下查询

查询

Select datename(month, p.EntryDate) month, 
        (select count(u.gender) from [HospitalManagement].[dbo].[Users] u
        where u.Id = p.User_Id and u.Gender = 'Female'
        group by u.Gender) female,
        (select count(u.gender) from [HospitalManagement].[dbo].[Users] u
        where u.Id = p.User_Id and u.Gender = 'Male'
        group by u.Gender) male
    from [HospitalManagement].[dbo].[Patients] p
    group by datename(month, p.EntryDate)

错误

Column 'HospitalManagement.dbo.Patients.User_Id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

以下是表格的创建语句(我使用 MSSql

-- Creating table 'Users'
CREATE TABLE [dbo].[Users] (
    [Id] bigint IDENTITY(1,1) NOT NULL,
    [Email] nvarchar(max)  NULL,
    [Password] nvarchar(max)  NULL,
    [UserName] nvarchar(max)  NULL,
    [Age] bigint  NULL,
    [Gender] nvarchar(max)  NULL,
    [NRIC] nvarchar(max)  NULL,
    [Comments] nvarchar(max)  NULL,
    [Address] nvarchar(max)  NULL,
    [ContactNo] nvarchar(max)  NULL,
    [FullName] nvarchar(max)  NULL
);
GO

-- Creating table 'Patients'
CREATE TABLE [dbo].[Patients] (
    [Id] bigint IDENTITY(1,1) NOT NULL,
    [Disease] nvarchar(max)  NULL,
    [Occupation] nvarchar(max)  NULL,
    [EntryDate] datetime  NULL,
    [EntryTime] time  NULL,
    [User_Id] bigint  NOT NULL
);
GO

3 个答案:

答案 0 :(得分:2)

如错误所示,您直接在select子句中使用User_Id列,该列在GROUP BY中不存在。

您可以将相关子查询更改为更快的LEFT JOIN(假设User_Id在Patients表中是唯一的)。

select
    datename(month, p.EntryDate) mon,
    count(case when u.Gender = 'Female' then 1 end) female_cnt,
    count(case when u.Gender = 'Male' then 1 end) male_cnt
from [Patients] p left join [Users] u
on p.User_Id = u.Id
group by datename(month, p.EntryDate);

编辑:

您可以使用查找CTE生成所有月份,然后像这样使用LEFT JOIN:

;WITH months(mn, mon) AS
(
    SELECT 1, DATENAME(MONTH,DATEADD(month,0,GETDATE())) mon
    UNION ALL
    SELECT mn+1, DATENAME(MONTH,DATEADD(MONTH,mn,GETDATE()))
    FROM months
    WHERE mn < 12
)
select
    m.mon mon,
    count(case when u.Gender = 'Female' then 1 end) female_cnt,
    count(case when u.Gender = 'Male' then 1 end) male_cnt
from months m left join [Patients] p 
on m.mon = datename(month, p.EntryDate)
left join [Users] u
on p.User_Id = u.Id
group by m.mon;

答案 1 :(得分:0)

您可以尝试以下查询:

 Select 
    datename(month, p.EntryDate) month,
    COUNT(IF(u.Gender = 'Male', 1, NULL) AS MaleCount,  
    COUNT(IF(u.Gender = 'Female', 1, NULL) AS FemaleCount
from 
    [HospitalManagement].[dbo].[Patients] p,[HospitalManagement].[dbo].[Users] u 
where 
    u.Id = p.User_Id 
group by 
    datename(month, p.EntryDate)

答案 2 :(得分:0)

这就是我们在MySQL或Oracle中的表现。虽然没有尝试过MSSQL。但由于这些是标准的SQL函数(并且在MSSQL中可用),因此它也适用于MSSQL。

Select  datename(month, p.EntryDate) month , SUM(CASE WHEN u.Gender = 'Male' THEN 1 ELSE 0) MaleCount, SUM(CASE WHEN u.Gender = 'Female' THEN 1 ELSE 0) FemaleCount,  
    from [HospitalManagement].[dbo].[Patients] p,[HospitalManagement].[dbo].[Users] u 
    where u.Id = p.User_Id 
    group by datename(month, p.EntryDate)

通常我会在特定性别的情况下添加1来获得结果。

注意:如果有任何语法错误,请告诉我错误,我可以更正。