在SQL Server中对列进行分组

时间:2018-05-12 11:46:17

标签: sql sql-server

我正在尝试将信用卡和借记卡帐号进行分组以进行货币交易。

http://sqlfiddle.com/#!18/67ecd/4/0

如果同一个信用卡和借记卡帐户有多笔交易,我可以进行分组。

CREATE Table TestTable 
(
    DebitAccountNumber NVARCHAR(10),
    CredtiAccountNumber NVARCHAR(10),
    Amount MONEY
)

INSERT INTO TestTable 
VALUES ('A', 'C', 10), ('C', 'A', 20), ('A', 'C', 40);

SELECT  
    DebitAccountNumber, 
    CredtiAccountNumber, 
    SUM(amount) 
FROM 
    TestTable
GROUP BY
    DebitAccountNumber, CredtiAccountNumber

由于信用卡和借记卡帐户在同一帐户中发生,因此预期输出为A - > C 30.

有人可以帮我查询一下吗?

3 个答案:

答案 0 :(得分:3)

我怀疑你想要:

select accountnumber, sum(amount)
from ((select DebitAccountNumber as accountnumber, - amount as amount
       from testtable
      ) union all
      (select CreditAccountNumber as accountnumber, amount
       from testtable
      )
     ) cd
group by accountnumber;

在SQL Server中,您可以使用apply

select v.accountnumber, sum(v.amount)
from testtable tt cross apply
     (values (debitaccountnumber, - amount), (creditaccountnumber, amount)
     ) v(accountnumber, amount)
group by v.accountnumber;

答案 1 :(得分:1)

WITH cte AS
 ( 
   SELECT
      -- "normalize" debitor and creditor to: account#1 < account#2
      CASE WHEN DebitAccountNumber < CreditAccountNumber THEN DebitAccountNumber  ELSE CreditAccountNumber END AS Account1,
      CASE WHEN DebitAccountNumber < CreditAccountNumber THEN CreditAccountNumber ELSE DebitAccountNumber  END AS Account2,
      -- adjust sign when accounts switched   
      CASE WHEN DebitAccountNumber < CreditAccountNumber THEN Amount              ELSE -Amount             END AS amount
   FROM TestTable
 )
SELECT
   Account1,
   Account2,
   Sum(amount) -- might be negative 
FROM cte
GROUP BY
   Account1,
   Account2
;

请参阅fiddle

编辑:

如果你想避免负数,你可以&#34;规范化&#34;它再次:

WITH normalized AS
 ( 
   SELECT
      -- "normalize" debitor and creditor to: account#1 < account#2
      CASE WHEN DebitAccountNumber < CreditAccountNumber THEN DebitAccountNumber  ELSE CreditAccountNumber END AS Account1,
      CASE WHEN DebitAccountNumber < CreditAccountNumber THEN CreditAccountNumber ELSE DebitAccountNumber  END AS Account2,
      -- adjust sign when accounts switched   
      CASE WHEN DebitAccountNumber < CreditAccountNumber THEN Amount              ELSE -Amount             END AS amount
   FROM TestTable
 ),
summed as
 (
   SELECT
      Account1,
      Account2,
      Sum(amount) as Amount -- might be negative 
   FROM normalized
   GROUP BY
      Account1,
      Account2
 )
select
   case when Amount > 0 then Account1 else Account2 end as Debitor,
   case when Amount > 0 then Account2 else Account1 end as Creditor,
   abs(Amount) as Amount
from summed
;

请参阅fiddle

答案 2 :(得分:0)

根据@GordonLinoff的方法,考虑到结果,您接受了@dnoeth,我建议的答案是:

SELECT v.CreditAccountNumber, v.DebitAccountNumber, SUM(v.Amount) AS SumAmount
FROM TestTable AS tt
CROSS APPLY
     (VALUES
        (DebitAccountNumber, CreditAccountNumber, Amount),
        (CreditAccountNumber, DebitAccountNumber, -Amount)
     ) AS v(DebitAccountNumber, CreditAccountNumber, Amount)
GROUP BY v.CreditAccountNumber, v.DebitAccountNumber
HAVING SUM(v.Amount) > 0
ORDER BY 1, 2;

这里是fiddle for it