简体   繁体   中英

SQL Aggregate function to filter data based on 3 columns

I have the below Claims data. I need to find the number of claims based on a certain age group, gender, and Health condition. I'm trying to figure out if there is a way to add TotalClaims per age group in the result table. Right now I've added Sum(d.totalclaims) in the below query which is wrong because it is filtered based on condition and gender and not age group. How to get claims based on all three conditions(age, condition, gender). Any ideas/suggestions, please!

SELECT c.condition, 
       a.gender, 
       Sum(CASE WHEN a.age BETWEEN 40 AND 50 THEN 1 END) AS Members_40_50_years, 
       Sum(d.totalclaims) 
FROM   (SELECT DISTINCT id, gender, age FROM   agetable) AS a 
       INNER JOIN (SELECT DISTINCT id, condition 
                   FROM   conditiontable) AS c 
               ON a.id = c.id 
       INNER JOIN (SELECT Count(DISTINCT claimid) AS TotalClaims, id 
                   FROM   claimstable group by id) d 
               ON d.id = a.id 
GROUP  BY gender, 
          condition 

Age Table

+----+--------+-----+
| ID | Gender | Age |
+----+--------+-----+
|  1 | M      |  45 |
|  2 | F      |  60 |
+----+--------+-----+

Condition Table

+----+--------------+
| ID |  Condition   |
+----+--------------+
|  1 | HeartFailure |
|  1 | Diabetes     |
|  2 | Diabetes     |
+----+--------------+

Claims Table

+----+---------+
| ID | ClaimID |
+----+---------+
|  1 | A11     |
|  1 | 345     |
|  1 | A32     |
|  2 | 542     |
|  2 | 675     |
+----+---------+

I'd look to group the ages into one column rather than having columns for each one.

Does something like this give you what you need?

SELECT
    A.Gender
    ,
        CASE
            WHEN A.Age BETWEEN 30 AND 40 THEN '30-40'
            WHEN A.Age BETWEEN 40 AND 50 THEN '40-50'
            --etc.
        END AgeGroup
    , CD.Condition
    , COUNT(*) TotalClaims
FROM
    agetable A
    JOIN conditiontable CD ON A.ID = CD.ID
    JOIN claimstable CL ON A.ID = CL.ID
GROUP BY
    A.Gender
    ,
        CASE
            WHEN A.Age BETWEEN 30 AND 40 THEN '30-40'
            WHEN A.Age BETWEEN 40 AND 50 THEN '40-50'
            --etc.
        END
    , CD.Condition

This is the query you are looking for:

drop table if exists #age, #condition, #claims 

create table #age
(
id      int,
gender  char(1),
Age     int
);

insert  into 
#age    values (1,'M',45), (2,'F',60)

create table #Conditon
(
Id          int,    
Condition   nvarchar(30)
);

insert      into 
#Conditon   values (1, 'HeartFailure'), (1,'Diabetes'), (2, 'Diabetes')

create table #claims    
(
Id      int,
ClaimId nvarchar(4)
)

insert  into 
#claims values (1, 'A11'), (1, '345'), (1, 'A32'), (2, '542'), (2, '675')



SELECT  a.gender
        , a.Age
        , con.Condition
        , count(distinct cl.ClaimId) as ClaimCnt
FROM    #claims cl
JOIN    #Conditon con
        on cl.Id = con.Id
join    #age a
        on a.id = cl.Id
group 
by      a.gender
        , a.Age
        , con.Condition

The age groups table is missing. Using Chris Mack's setup

create table #age
(
id      int,
gender  char(1),
Age     int
);

insert  into 
#age    values (1,'M',45), (2,'F',60)

create table #Condition
(
Id          int,    
Condition   nvarchar(30)
);

insert      into 
#Condition   values (1, 'HeartFailure'), (1,'Diabetes'), (2, 'Diabetes');

create table #claims    
(
Id      int,
ClaimId nvarchar(4)
);


insert  into 
#claims values (1, 'A11'), (1, '345'), (1, 'A32'), (2, '542'), (2, '675');

-- table of ranges
create table #agerange    
(
rfrom   int,
rto int
);
insert  into 
#agerange values (0,39),(40,50),(51,70);

SELECT c.condition, 
       a.gender, 
       cast(r.rfrom as varchar(3))+'_'+cast(r.rto as varchar(3)) range,
       Sum(d.totalclaims) 
FROM   (SELECT DISTINCT id, gender, age FROM  #age) AS a 
       INNER JOIN #agerange r ON a.age BETWEEN r.rfrom and r.rto
       INNER JOIN (SELECT DISTINCT id, condition 
                   FROM   #condition) AS c 
               ON a.id = c.id 
       INNER JOIN (SELECT Count(DISTINCT claimid) AS TotalClaims, id 
                   FROM   #claims group by id) d 
               ON d.id = a.id 
GROUP  BY gender, 
          condition,
          cast(r.rfrom as varchar(3))+'_'+cast(r.rto as varchar(3));

I don't understand why you need those DISTINCT selects, but I've kept it as is.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM