使用 SQL 清理数据 - 取列差异

Clean Data Using SQL - Take Column Difference

我在SQL中有如下数据:

实际Table

+-------------+--------+------+
|     Id      | Weight | Type |
+-------------+--------+------+
| 00011223344 |     35 | A    |
| 00011223344 |     10 | A    |
| 12311223344 |    100 | B    |
| 00034343434 |     25 | A    |
| 00034343434 |     25 | A    |
| 99934343434 |    200 | C    |
| 88855667788 |    100 | D    |
+-------------+--------+------+

ID 的长度始终为 11,数据类型为 varchar。我需要从上面的 table 创建一个列 Actual WeightActual ID

Actual Id 依赖于列 ID。如果 ID 以 000 开头,那么我们需要从 ID 列中找到不以 000 开头但之后的字符(即从右边开始的 8 个字符)相似的 ID。匹配的 ID 为 Actual Id。例如,如果我们查看前 3 个 ID,前 2 个以 000 开头,另一个不以 000 开头且包含右起类似 8 个字符的 ID 可以在第 3 行中找到,即 12311223344因此在派生列 Actual ID 中,前两行将 Actual Id 作为 12311223344.

Actual Weight 取决于 2 列 IDWeight 中的值。如果对于任何不以 000 开头但包含另一个以 000 开头的条目的 Id,我们需要根据上述条件对列 Id 进行分组。然后我们需要为不以 000 开头的 Id 重新计算 Weight,方法是将所有以 000 开头的权重相加,并与不以 [= 开头的权重相加=18=].

例如,如果我们查看前 3 行,在第 3 行中我们有 Id123 开头并且具有从右边开始有 8 位数字的条目,除了它们以 [= 开头18=] 而不是 123(即第 1 行和第 2 行)。对于以 000 开头的情况,Actual Weight 将类似于 Weight,但对于以 123 开头的情况,Actual Weight 将是 100-(35+10)

我正在寻找可以创建这 2 个派生列而无需创建任何其他 table/view.

的查询

期望输出

+-------------+-------------+--------+---------------+------+
|     Id      |  Actual ID  | Weight | Actual Weight | Type |
+-------------+-------------+--------+---------------+------+
| 00011223344 | 12311223344 |     35 |            35 | A    |
| 00011223344 | 12311223344 |     10 |            10 | A    |
| 12311223344 | 12311223344 |    100 |            55 | B    |
| 00034343434 | 99934343434 |     25 |            25 | A    |
| 00034343434 | 99934343434 |     25 |            25 | A    |
| 99934343434 | 99934343434 |    200 |           150 | C    |
| 88855667788 | 88855667788 |    100 |           100 | D    |
+-------------+-------------+--------+---------------+------+

嗯嗯。 . .如果我关注这个:

select t.*,
       (case when id like '000%' then weight
             else weight - sum(case when id like '000%' then weight else 0 end) over (partition by actual_id)
        end) as actual_weight
from (select t.*,
             max(id) over (partition by stuff(id, 1, 3, '')) as actual_id
      from t
     ) t;

Here 是一个 db<>fiddle.