我有一张桌子:
+---------+--------------------+--------------------------+
| imd_id | Total TRx per Plan | plan name |
+---------+--------------------+--------------------------+
| 1111005 | 397.1556 | Medicaid Illinois (Idpa) |
| 1111005 | 25.7691 | Self Pay |
| 1111005 | 24.4355 | Tricare North Region |
| 1111005 | 15.0312 | 0 |
| 1111005 | 8.8425 | 0 |
| 1111005 | 8.3139 | 0 |
| 1111005 | 7.0534 | 0 |
| 1111005 | 6.2588 | 0 |
| 1111005 | 6.0358 | Bravo Health |
| 1111005 | 5.9872 | 0 |
| 1111531 | 133.9664 | Medicaid Al |
| 1111531 | 29.2318 | 0 |
| 1111531 | 23.2499 | 0 |
| 1111531 | 21.9774 | 0 |
| 1111531 | 14.9269 | 0 |
| 1111531 | 10.1903 | Self Pay |
| 1111531 | 5.4962 | 0 |
| 1111531 | 5.3409 | Bcbs Federal |
| 1111531 | 4.4801 | 0 |
| 1111531 | 3.8003 | 0 |
+---------+--------------------+--------------------------+
并尝试生成看起来像这样的数据
+---------+--------------------------+----------+---------------+-----------+----------------------+----------+
| imd_id | TopFirstPlan | TopFirst | TopSecondPlan | TopSecond | TopThirdPlan | TopThird |
+---------+--------------------------+----------+---------------+-----------+----------------------+----------+
| 1111005 | Medicaid Illinois (Idpa) | 0.78 | Self Pay | 0.05 | Tricare North Region | 0.04 |
| 1111531 | MEDICAID ALABAMA (AL) | 0.5 | Self Pay | 0.04 | Bcbs Federal | 0.02 |
+---------+--------------------------+----------+---------------+-----------+----------------------+----------+
请注意,创建TOPFIRST,TOP SECOND,TOP THIRD的方式是相应的Total TRx per Plan
除以特定IMD_ID的计划总和。
select distinct a.imd_id,'topone'=
(select top 1 totalrxperplan
from book1 b
where b.imd_id = a.imd_id)/
(select SUM(totalrxperplan)
from book1 b
where b.imd_id = a.imd_id)
,'topplan2'=
(select top 1 xifinplanname
from book1 b
where b.imd_id = a.imd_id)
from book1 a
order by 1 asc
此查询将返回:
+---------+--------------------------+----------+
| imd_id | TopFirstPlan1 | TopFirst |
+---------+--------------------------+----------+
| 1111005 | Medicaid Illinois (Idpa) | 79% |
| 1111531 | MEDICAID ALABAMA (AL) | 53% |
+---------+--------------------------+----------+
但我需要添加其他列。
请注意,我们会ignore the plan name where it is 0
答案 0 :(得分:3)
CREATE TABLE #x(imd_id INT, totalrxperplan FLOAT, xifinplanname NVARCHAR(64));
INSERT #x VALUES
(1111005,397.1556 ,'Medicaid Illinois (Idpa)'),
(1111005,25.7691 ,'Self Pay '),
(1111005,24.4355 ,'Tricare North Region '),
(1111005,15.0312 ,'0 '),
(1111005,8.8425 ,'0 '),
(1111005,8.3139 ,'0 '),
(1111005,7.0534 ,'0 '),
(1111005,6.2588 ,'0 '),
(1111005,6.0358 ,'Bravo Health '),
(1111005,5.9872 ,'0 '),
(1111531,133.9664 ,'Medicaid Al '),
(1111531,29.2318 ,'0 '),
(1111531,23.2499 ,'0 '),
(1111531,21.9774 ,'0 '),
(1111531,14.9269 ,'0 '),
(1111531,10.1903 ,'Self Pay '),
(1111531,5.4962 ,'0 '),
(1111531,5.3409 ,'Bcbs Federal '),
(1111531,4.4801 ,'0 '),
(1111531,3.8003 ,'0 ');
现在查询:
WITH cte1(id,pn,s) AS
(
SELECT imd_id, xifinplanname,
ROUND(totalrxperplan/SUM(totalrxperplan) OVER (PARTITION BY imd_id),2,1)
FROM #x WHERE xifinplanname <> '0'
),
cte2(id,pn,s,rn) AS
(
SELECT id,pn,s,ROW_NUMBER() OVER (PARTITION BY id ORDER BY s DESC)
FROM cte1
)
SELECT
id,
TopFirstPlan = MAX(CASE WHEN rn = 1 THEN pn END),
TopFirst = MAX(CASE WHEN rn = 1 THEN s END),
TopSecondPlan = MAX(CASE WHEN rn = 2 THEN pn END),
TopSecond = MAX(CASE WHEN rn = 2 THEN s END),
TopThirdPlan = MAX(CASE WHEN rn = 3 THEN pn END),
TopThird = MAX(CASE WHEN rn = 3 THEN s END)
FROM cte2
WHERE rn <= 3
GROUP BY id;
如果我的假设是正确的,输出数字与你的不匹配,因为你想要包含偶数&#39; 0&#39;计划在总计中,而不是在结果中,那么你可以只改变where子句:
WITH cte1(id,pn,s) AS
(
SELECT imd_id, xifinplanname,
ROUND(totalrxperplan/SUM(totalrxperplan) OVER (PARTITION BY imd_id), 2, 1)
FROM #x -- < -- removed where clause from here
),
cte2(id,pn,s,rn) AS
(
SELECT id,pn,CONVERT(DECIMAL(3,2), s),ROW_NUMBER() OVER
(PARTITION BY id ORDER BY s DESC)
FROM cte1 WHERE pn <> '0' -- <-- moved where clause here
)
SELECT
id,
TopFirstPlan = MAX(CASE WHEN rn = 1 THEN pn END),
TopFirst = MAX(CASE WHEN rn = 1 THEN s END),
TopSecondPlan = MAX(CASE WHEN rn = 2 THEN pn END),
TopSecond = MAX(CASE WHEN rn = 2 THEN s END),
TopThirdPlan = MAX(CASE WHEN rn = 3 THEN pn END),
TopThird = MAX(CASE WHEN rn = 3 THEN s END)
FROM cte2
WHERE rn <= 3
GROUP BY id;
答案 1 :(得分:1)
如果我理解正确,关键是在每个imd_id中按总计计算组。您可以使用windows函数row_number()。
执行此操作最终查询类似于:
select imd_id,
max(case when therank = 1 then plan_name end) as firstplan,
max(case when therank = 1 then tot/imd_tot end) as firstplan_ratio,
...
from (select t.*, row_number() over (partition by imd_id order by tot desc) as therank,
sum(tot) over (partition by imd_id) as imd_tot
from (select imd_id plan_name, sum(total_trx_per_plan) as tot
from t
group by imd_id plan_name
) t
) t
group by imd_id
答案 2 :(得分:1)
我不确定Aaron的总数,而不是per-id总数,是OP想要的,所以这是我的建议,基本上是Aaron建议但具有不同的小数值:
更新以更正错误副本,并解释为“0”规则。
with R1 as (
select
imd_id,
[plan name],
1e0*[Total TRx per Plan]/sum([Total TRx per Plan]) over (partition by imd_id) as pct,
row_number() over (
partition by imd_id
order by case when [plan name] = '0' then -1 else [Total TRx per Plan] end desc
) as rn
from @Test
)
select
imd_id,
max(case when rn=1 then [plan name] end) as TopFirstPlan,
max(case when rn=1 then pct end) as TopFirst,
max(case when rn=2 then [plan name] end) as TopSecondPlan,
max(case when rn=2 then pct end) as TopSecond,
max(case when rn=3 then [plan name] end) as TopThirdPlan,
max(case when rn=3 then pct end) as TopThird
from R1
where rn <= 3
group by imd_id
order by imd_id
答案 3 :(得分:1)
DECLARE @Test TABLE
(
imd_id INT NOT NULL,
[Total TRx per Plan] NUMERIC(9,4) NOT NULL,
[plan name] NVARCHAR(50) NOT NULL
);
INSERT @Test (imd_id, [Total TRx per Plan], [plan name])
VALUES (1111005,397.1556,'Medicaid Illinois (Idpa) ')
,(1111005,25.7691 ,'SelfPay')
,(1111005,24.4355 ,'TricareNorthRegion')
,(1111005,15.0312 ,'0')
,(1111005,8.8425 ,'0')
,(1111005,8.3139 ,'0')
,(1111005,7.0534 ,'0')
,(1111005,6.2588 ,'0')
,(1111005,6.0358 ,'BravoHealth')
,(1111005,5.9872 ,'0')
,(1111531,133.9664,'MedicaidAl')
,(1111531,29.2318 ,'0')
,(1111531,23.2499 ,'0')
,(1111531,21.9774 ,'0')
,(1111531,14.9269 ,'0')
,(1111531,10.1903 ,'SelfPay')
,(1111531,5.4962 ,'0')
,(1111531,5.3409 ,'BcbsFederal')
,(1111531,4.4801 ,'0')
,(1111531,3.8003 ,'0');
SELECT c.imd_id,
MAX(CASE WHEN c.RowNum = 1 THEN c.[plan name] END) AS TopFirstPlan,
MAX(CASE WHEN c.RowNum = 1 THEN c.TruncatedValue END) AS TopFirst,
MAX(CASE WHEN c.RowNum = 2 THEN c.[plan name] END) AS TopSecondPlan,
MAX(CASE WHEN c.RowNum = 2 THEN c.TruncatedValue END) AS TopSecond,
MAX(CASE WHEN c.RowNum = 3 THEN c.[plan name] END) AS TopThirdPlan,
MAX(CASE WHEN c.RowNum = 3 THEN c.TruncatedValue END) AS TopThird
FROM
(
SELECT b.imd_id,
b.[plan name],
b.TruncatedValue,
ROW_NUMBER() OVER(PARTITION BY b.imd_id ORDER BY b.TruncatedValue DESC) AS RowNum
FROM
(
SELECT a.imd_id,
a.[plan name],
ROUND(a.[Total TRx per Plan] / SUM(a.[Total TRx per Plan]) OVER(PARTITION BY a.imd_id), 2, 1) AS TruncatedValue
FROM @Test a
) b
WHERE b.[plan name] <> '0'
) c
WHERE c.RowNum < 4
GROUP BY c.imd_id
结果:
imd_id TopFirstPlan TopFirst TopSecondPlan TopSecond TopThirdPlan TopThird
------- ------------------------ ------------------------------- ------------- ------------------------------- ------------------ -------------------------------
1111005 Medicaid Illinois (Idpa) 0.78000000000000000000000000000 SelfPay 0.05000000000000000000000000000 TricareNorthRegion 0.04000000000000000000000000000
1111531 MedicaidAl 0.53000000000000000000000000000 SelfPay 0.04000000000000000000000000000 BcbsFederal 0.02000000000000000000000000000
答案 4 :(得分:1)
我提出了这样的疑问:
WITH totals AS (
SELECT imd_id, sum(t_trx_per_plan) AS ttl
FROM plans
GROUP BY imd_id),
ranks(imd_id,t_trx_per_plan,plan_name,prc,rank) AS (
SELECT p.imd_id,p.t_trx_per_plan,p.plan_name,
CAST(p.t_trx_per_plan / t.ttl * 100 AS NUMERIC(5,2)) AS prc,
rank() OVER (PARTITION BY p.imd_id
ORDER BY (p.t_trx_per_plan / t.ttl * 100) DESC) AS rank
FROM plans p
JOIN totals t ON t.imd_id = p.imd_id
WHERE p.plan_name != '0')
SELECT
ttl.imd_id,
f.plan_name AS "FirstPlan",f.prc AS "First",
s.plan_name AS "SecondPlan",s.prc AS "Second",
t.plan_name AS "ThirdPlan",t.prc AS "Third"
FROM totals ttl
LEFT JOIN ranks f ON f.imd_id = ttl.imd_id AND f.rank = 1
LEFT JOIN ranks s ON s.imd_id = ttl.imd_id AND s.rank = 2
LEFT JOIN ranks t ON t.imd_id = ttl.imd_id AND t.rank = 3;
第一个CTE totals
正在列出imd_id
以及每个计划的总交易量。第二次CTE ranks
是排名计划。请注意,我使用了rank()
函数,如果计划每个计划的事务数量相同,则会产生相同的排名。如果要正确处理此类情况,则需要使用row_number()
窗口函数并在ORDER BY
子句中添加额外的OVER
列,唯一的可能是使用:
row_number() OVER (PARTITION BY p.imd_id
ORDER BY (p.t_trx_per_plan / t.ttl * 100) DESC, p.plan_name) AS rank
您可以检查输出here。