可以使用2个CTE以外的内容解决此查询吗?

时间:2018-10-16 15:03:38

标签: tsql common-table-expression window-functions

我正在使用随机生成的虚构名称和数据针对称为CLAIMS的虚构保险蛤lam表编写查询。

在称为PRIMARY_DX的列中有5个不同的类别: 酒精中毒,焦虑症,抑郁症,精神病,药物滥用症

其他主要列是PATIENT_ID和CLAIM_PAID_AMT

我想对每个PRIMARY_DX的每个患者的CLAIM_PAID_AMT求和,并仅列出每个PRIMARY_DX的总和最高的前5名患者

我想到的唯一方法是使用两个通用表表达式,其中在CTE1中,我按PRIMARY_DX和PATIENT_ID进行分区,然后对每个PATIENT的CLAIM_PAID_AMT进行求和。

然后在CTE2中,我在CTE1上使用ROW_NUMBER函数,按PRIMARY_DX进行分区,并按TotalClaims DESC排序,然后从每个PRIMARY_DX中选择前5名。

我编写SQL的时间不到2年,并且想知道这是否可以在一个CTE中完成,或者可以通过某种形式的Cross Apply来完成?

我在下面包括我的代码和输出。

;WITH CTE1 AS
(
select PRIMARY_DX, PATIENT_ID, TotalClaims = SUM(CLAIM_PAID_AMT)
OVER (PARTITION BY PRIMARY_DX, PATIENT_ID ORDER BY PATIENT_ID, CLAIM_PAID_AMT DESC)
from claims
)
, 
CTE2 AS
(SELECT *, RowCounter = ROW_NUMBER() OVER (PARTITION BY PRIMARY_DX ORDER BY TotalClaims DESC) FROM CTE1)
select CTE2.PRIMARY_DX, CTE2.TotalClaims from CTE2
where RowCounter <= 5
order by CTE2.PRIMARY_DX, CTE2.TotalClaims DESC

酒精中毒3737.51乔·史密斯

酒精中毒3282.07苏西(Suzie)家庭主妇

酒精中毒3207.72乔伊·史都默

酒精中毒3040.52生锈的指甲锉

酗酒2997.02大本钟

焦虑症3291.14 Norman Pigsty

焦虑症3113.05 Billy Bob

焦虑症3101.13 Rachel南极洲

焦虑症3058.52约翰·约翰

焦虑症3021.98凯西·欧罗巴

大萧条3466.14弗雷达·贝加利(

抑郁3279.25罗恩(Ron Jeremize)

抑郁症3140.43 Sharon Sharonaz

抑郁3119.26艾莉·凯特

抑郁症3118.54 Biff Biffstoferson

精神病3098.13詹姆斯大富翁

精神病2991.23错误的莱昂

精神病2857.69 Lucie Ratched-McMurphy

精神病2678.88 Billy Bibbitz

精神病2602.24 Sam Zypperzsky

物质使用障碍3435.27唐纳德·达卡罗纳威茨

物质使用障碍3300.33米奇捕鼠器

物质使用障碍3285.41 Hector Heathercoatz

物质使用障碍3179 Erin GoBragh

物质使用障碍3147.09 Bono Edgerstein

1 个答案:

答案 0 :(得分:1)

您只需要一个子查询或CTE,因为您可以在ROW_NUMBER()中使用聚合。

以下是使用子查询的一种方法:

SELECT *
FROM (
    SELECT PRIMARY_DX, PATIENT, SUM(CLAIM_PAID_AMT) AS CLAIM_PAID_AMT,
        ROW_NUMBER() OVER (PARTITION BY PRIMARY_DX ORDER BY SUM(CLAIM_PAID_AMT) DESC) AS RowId
    FROM Claims GROUP BY PRIMARY_DX, PATIENT
) T
WHERE RowId <= 5

如果您喜欢CTE:

;WITH CTE AS (
    SELECT PRIMARY_DX, PATIENT, SUM(CLAIM_PAID_AMT) AS CLAIM_PAID_AMT,
        ROW_NUMBER() OVER (PARTITION BY PRIMARY_DX ORDER BY SUM(CLAIM_PAID_AMT) DESC) AS RowId
    FROM Claims GROUP BY PRIMARY_DX, PATIENT
) SELECT * FROM CTE WHERE RowId <= 5