在 2 个给定类型的查询中减去两列,否则保持原样

Subtract two columns in a query for 2 given types, otherwise leave as is

CREATE TABLE #test (Type1 VARCHAR(10),NUM1 VARCHAR(10), Grp1 VARCHAR(10), Amt1 INT, Amt2 INT)

INSERT INTO #test
(
  Type1,
  NUM1,
  Grp1,
  Amt1,
  Amt2
)
VALUES
  ('CA',    'TIX_1',    'GG', 3, 5),
  ('PR',    'TIX_1',    'GG', 2, 1),
  ('PR',    'TIX_2',    'XX', 1, 5)

假设我在 table 中有这样的数据:

Type1   NUM1    Grp1    Amt1    Amt2
CA      TIX_1   GG      3       5
PR      TIX_1   GG      2       1
PR      TIX_2   XX      1       5

对于给定的 NUM1,我将有 2 个 Type1(CA,PR)或 1 个 Typ1,CA 或 PR。

目标是为那些有 PR 和 CA 记录的 NUM1 做一个简单的减法,但是如果只有一个 Type1(CA 或 PR)的 NUM1 则保持原样

目标:

NUM1    Grp1    Amt1    Amt2
TIX_1   GG      1       4
TIX_2   XX      1       5

我正在尝试使用 FULL JOIN 来执行此操作,如下所示:

SELECT t1.NUM1,
       t1.Grp1,
       t1.Amt1 - t2.Amt1 AS X, --(CA - PR )
       t1.Amt2 - t2.Amt2 AS Y  --(CA - PR )
FROM #test t1 FULL JOIN #test t2 
     ON t1.NUM1=t2.NUM1 
     AND t1.Grp1=t2.Grp1 
     AND t2.Type1='PR'
WHERE t1.Type1='CA'

上述查询的结果:

 NUM1   Grp1    X   Y
 TIX_1  GG      1   4

对于 TIX_2 - 只有 1 个 Type1 = PR,所以没有数据被提取,但是有没有办法可以加入数据并减去它来实现我的目标?

@NBK 编辑

 NUM1   Grp1    X   Y
 TIX_1    GG    1   4
 TIX_1    GG    0   0
 TIX_2    XX    0   0
  NULL    NULL  NULL    NULL

你的最小可复制示例做得很好!

一种适用于此数据集但可能不适用于更复杂的数据集的方法是直接 group by 和条件总和,例如

select min(Type1), NUM1, Grp1
    , case when min(Type1) = 'CA' then sum(Amt1 * case when Type1 = 'CA' then 1 else -1 end) else sum(Amt1) end
    , case when min(Type1) = 'CA' then sum(Amt2 * case when Type1 = 'CA' then 1 else -1 end) else sum(Amt2) end
from #test
group by NUM1, Grp1;

一种更复杂的方法,适用于更复杂的数据集,将使用 CTE。

  1. 在第一个 cte 中获取每个 NUM1
  2. 的行数
  3. 然后在第二个 cte 中得到一个行号,以及 NUM1 的条件和。行号允许我们随后仅过滤每个 NUM1 的第一行。条件总和允许我们对给定 NUM1 的金额求和,仅在 NUM1.
  4. 有多行时反转 Type1='PA'
with cte1 as (
    select *
        , count(*) over (partition by NUM1) Cnt
    from #test
), cte2 as (
    select Type1, NUM1, Grp1, Amt1, Amt2, rn
        , row_number() over (partition by NUM1 order by Type1) rn
        , sum(Amt1 * case when Type1 = 'CA' or Cnt = 1 then 1 else -1 end) over (partition by NUM1) Amt11
        , sum(Amt2 * case when Type1 = 'CA' or Cnt = 1 then 1 else -1 end) over (partition by NUM1) Amt22
    from cte1
)
select Type1, NUM1, Grp1, Amt11, Amt22
from cte2
where rn = 1;