分区依据 - 对不包括最大值的所有值求和
Partition By - Sum all values Excluding Maximum Value
我有数据如下
+----+------+--------+
| ID | Code | Weight |
+----+------+--------+
| 1 | M | 200 |
| 1 | 2A | 50 |
| 1 | 2B | 50 |
| 2 | | 350 |
| 2 | M | 350 |
| 2 | 3A | 120 |
| 2 | 3B | 120 |
| 3 | 5A | 100 |
| 4 | | 200 |
| 4 | | 100 |
+----+------+--------+
对于 ID 1
,最大权重是 200,我想从 ID 1
中减去所有权重的总和,除了最大值 200
。
可能有 2 行包含同一 ID 的最大值的情况。对于 ID 2
的示例,我们有 2 行包含最大值,即 350
。在这种情况下,我想对除最大值以外的所有值求和。但我会为包含最大值的 2 行中的 1 行标记权重 0。该行将是 Code
是 NULL/Blank.
的那一行
如果 ID 只有 1 行,则该行将保持原样。
另一种情况可能是只有一行包含最大权重,但 Code
是 NULL/Blank,在这种情况下,我们将简单地执行我们为 ID 1
所做的操作。对除最大值以外的所有值求和并从包含最大值的行中减去。
期望输出
+----+------+--------+---------------+
| ID | Code | Weight | Actual Weight |
+----+------+--------+---------------+
| 1 | M | 200 | 100 |
| 1 | 2A | 50 | 50 |
| 1 | 2B | 50 | 50 |
| 2 | | 350 | 0 |
| 2 | M | 350 | 110 |
| 2 | 3A | 120 | 120 |
| 2 | 3B | 120 | 120 |
| 3 | 5A | 100 | 100 |
| 4 | | 200 | 100 |
| 4 | | 100 | 100 |
+----+------+--------+---------------+
我想创建列 Actual Weight
,如上所示。我找不到通过排除最大值和创建列 Actual Weight
.
来应用分区的方法
嗯。 . .我认为您只需要 window 函数和条件逻辑:
select t.*,
(case when 1 = row_number() over (partition by id order by weight desc, (case when code <> '' then 2 else 1 end))
then weight - sum(case when weight <> max_weight then weight else 0 end) over (partition by id)
else weight
end) as actual_weight
from (select t.*,
max(weight) over (partition by id, code) as max_weight
from t
) t
dense_rank()
标识最大权重的行,dr = 1 是最大权重的行
row_number()
区分 Code = blank 的最大重量行与其他行
with cte as
(
select *,
dr = dense_rank() over (partition by ID order by [Weight] desc),
rn = row_number() over (partition by ID order by [Weight] desc, Code desc)
from tbl
)
select *,
ActWeight = case when dr = 1 and rn <> 1
then 0
when dr = 1 and rn = 1
then [Weight]
- sum(case when dr <> 1 then [Weight] else 0 end) over (partition by ID)
else [Weight]
end
from cte
我有数据如下
+----+------+--------+
| ID | Code | Weight |
+----+------+--------+
| 1 | M | 200 |
| 1 | 2A | 50 |
| 1 | 2B | 50 |
| 2 | | 350 |
| 2 | M | 350 |
| 2 | 3A | 120 |
| 2 | 3B | 120 |
| 3 | 5A | 100 |
| 4 | | 200 |
| 4 | | 100 |
+----+------+--------+
对于 ID 1
,最大权重是 200,我想从 ID 1
中减去所有权重的总和,除了最大值 200
。
可能有 2 行包含同一 ID 的最大值的情况。对于 ID 2
的示例,我们有 2 行包含最大值,即 350
。在这种情况下,我想对除最大值以外的所有值求和。但我会为包含最大值的 2 行中的 1 行标记权重 0。该行将是 Code
是 NULL/Blank.
如果 ID 只有 1 行,则该行将保持原样。
另一种情况可能是只有一行包含最大权重,但 Code
是 NULL/Blank,在这种情况下,我们将简单地执行我们为 ID 1
所做的操作。对除最大值以外的所有值求和并从包含最大值的行中减去。
期望输出
+----+------+--------+---------------+
| ID | Code | Weight | Actual Weight |
+----+------+--------+---------------+
| 1 | M | 200 | 100 |
| 1 | 2A | 50 | 50 |
| 1 | 2B | 50 | 50 |
| 2 | | 350 | 0 |
| 2 | M | 350 | 110 |
| 2 | 3A | 120 | 120 |
| 2 | 3B | 120 | 120 |
| 3 | 5A | 100 | 100 |
| 4 | | 200 | 100 |
| 4 | | 100 | 100 |
+----+------+--------+---------------+
我想创建列 Actual Weight
,如上所示。我找不到通过排除最大值和创建列 Actual Weight
.
嗯。 . .我认为您只需要 window 函数和条件逻辑:
select t.*,
(case when 1 = row_number() over (partition by id order by weight desc, (case when code <> '' then 2 else 1 end))
then weight - sum(case when weight <> max_weight then weight else 0 end) over (partition by id)
else weight
end) as actual_weight
from (select t.*,
max(weight) over (partition by id, code) as max_weight
from t
) t
dense_rank()
标识最大权重的行,dr = 1 是最大权重的行
row_number()
区分 Code = blank 的最大重量行与其他行
with cte as
(
select *,
dr = dense_rank() over (partition by ID order by [Weight] desc),
rn = row_number() over (partition by ID order by [Weight] desc, Code desc)
from tbl
)
select *,
ActWeight = case when dr = 1 and rn <> 1
then 0
when dr = 1 and rn = 1
then [Weight]
- sum(case when dr <> 1 then [Weight] else 0 end) over (partition by ID)
else [Weight]
end
from cte