首页 > 解决方案 > 如何根据日期和相同的 PK 个人编号找到两个总和的差异

问题描述

我需要找到重复的个人 ID 并确定哪些个人 ID 得到了改进。例如,对于每个 IndividualID,我需要 C_Q1、C_Q2、C_Q3、C_Q4、C_Q5 的总和,并根据日期和 1 是最大的改进,5 是最小的改进,如果第二个总和小于第一个数字,并将通过 UpdateDate 确定第一个数字是最早的日期,第二个数字是较晚的日期。对于 Anxiety_Arr、Hyper_Arr、Exagg_Arr、Anxiety_Dep、Hyper_Dep、Exagg_Dep,1 是最小的改进,0 是最大的改进,因此在将它们相加后,如果第二个总和小于第一个总和,则将计算在内。

在此处输入图像描述

这是获得我需要的总和的代码,但随后需要帮助来了解如何比较每个 individualID 的第一个和第二个数字以及第二个总和低于第一个总和的个人计数。

    select distinct
             IND.Individuals_IndividualID 
       ,     C.ATQChild_IndividualID
       ,     ANS.ANS_IndividualID
       ,     C.UpdateDate as ATQChild_UpdateDate
       ,     ANS.UpdateDate as ANS_UpdateDate
       ,     c.q1_c as C_Q1
       ,     c.q2_c as C_Q2
       ,     c.q3_c as C_Q3
       ,     c.q4_c as C_Q4
       ,     c.q5_c as C_Q5
       ,     Sum(isnull(cast(Q1_c as int),0)) + Sum(isnull(cast(Q2_c as int),0)) + Sum(isnull(cast(Q3_c as int),0)) + Sum(isnull(cast(Q4_c as int),0)) + Sum(isnull(cast(Q5_c as int),0)) as ChildSum
       ,     Sum(isnull(cast(anxiety_arr as int),0)) + Sum(isnull(cast(hyper_arr as int),0)) + Sum(isnull(cast(exagg_arr as int),0)) as ANS_ArrSum
       ,     Sum(isnull(cast(anxiety_dep as int),0)) + Sum(isnull(cast(hyper_dep as int),0)) + Sum(isnull(cast(exagg_dep as int),0)) as ANS_DepSum
        ,   CASE WHEN (ANS.[anxiety_arr])='TRUE' THEN 1 ELSE 0 END as Anxiety_Arr
        ,   CASE WHEN (ANS.[hyper_arr])='TRUE' THEN 1 ELSE 0 END as Hyper_Arr
        ,   CASE WHEN (ANS.[exagg_arr])='TRUE' THEN 1 ELSE 0 END as Exagg_Arr
        ,   CASE WHEN (ANS.[anxiety_dep])='TRUE' THEN 1 ELSE 0 END as Anxiety_Dep
        ,   CASE WHEN (ANS.[hyper_dep])='TRUE' THEN 1 ELSE 0 END as Hyper_Dep
        ,   CASE WHEN (ANS.[exagg_dep])='TRUE' THEN 1 ELSE 0 END as Exagg_Dep 
from DBO.tb_cdcp_individuals ind
left join DBO.tb_cdcp_ATQChild c on c.[tb_cdcp_individuals] = ind.[tb_cdcp_individuals]
left join DBO.tb_cdcp_ans_checklist ANS on ans.[tb_cdcp_individuals] = ind.[tb_cdcp_individuals]
group by IND.tb_cdcp_individuals,C.[tb_cdcp_individuals],ANS.[tb_cdcp_individuals],C.UpdateDate,ANS.UpdateDate    
       ,     c.q1_c 
       ,     c.q2_c 
       ,     c.q3_c 
       ,     c.q4_c
       ,     c.q5_c 
       ,     ANS.Anxiety_Arr
       ,     ANS.hyper_arr
       ,     ANS.exagg_arr
       ,     ANS.Anxiety_Dep
       ,     ANS.Hyper_Dep
       ,     ANS.Exagg_Dep

标签: sqlsql-server

解决方案


您可以使用滞后/领先功能来比较 ID 的连续记录。例如,对于以下示例(假设表名为 temp):

身份证日期 CQ1To5

2019 年 1 月 1 日 10

2019 年 1 月 2 日 5

select *,lag(CQ1To5,1) Over(Partition by ID Order by Date) as lag_date,
Case when lag(CQ1To5,1) Over(Partition by ID Order by Date) is NULL then 0
when lag(CQ1To5,1) Over(Partition by ID Order by Date)<CQ1To5 then 1 else 0 end as Flag from temp

这应该为您提供以下输出:

ID 日期 CQ1To5 Lag_date 标志

2019 年 1 月 1 日 10 5 1

1 2019 年 1 月 2 日 5 空 0

只要 ID 的下一条记录是改进的,您的标志值就应该是 1。您可以修改此查询以满足您的特定需求。希望这可以帮助。

注意:CQ1to5 表示您提到的所有 5 个字段的总和

您可以使用连接和行号执行相同操作:

select *,Row_number() Over(Partition by ID Order by Date) as rownum
into #temp1
from #temp

select a.*,b.CQ1to5,case when a.CQ1to5<b.CQ1to5 then 1 else 0 end as flag
into #temp2
from #temp1 a left join #temp1 b on a.id=b.id and a.rownum=b.rownum+1

select *,row_number() over(Partition by ID,flag order by Date) as rownum1
into #temp3
from #temp2

UPDATE #temp3
SET flag=0
where flag=1 and rownum1>1

推荐阅读