在 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。
- 在第一个
cte
中获取每个 NUM1
的行数
- 然后在第二个
cte
中得到一个行号,以及 NUM1
的条件和。行号允许我们随后仅过滤每个 NUM1
的第一行。条件总和允许我们对给定 NUM1
的金额求和,仅在 NUM1
. 有多行时反转 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;
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。
- 在第一个
cte
中获取每个NUM1
的行数
- 然后在第二个
cte
中得到一个行号,以及NUM1
的条件和。行号允许我们随后仅过滤每个NUM1
的第一行。条件总和允许我们对给定NUM1
的金额求和,仅在NUM1
. 有多行时反转
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;