简体   繁体   中英

SQL - Difficult query - SUM multiple rows into columns

I am having a small challenge with a query I am trying to develop.

Here is what my table looks like:-

Accounts Table

ClientNo        AccountType          Balance
  1234             SUP1                25
  1234            SUP1.1               35
  1234             RET1                20
  1111             SUP1                50
  1111             DIS4                60

I am trying to get to a result that looks like the following:-

ClientNo   TotSupBal   TotSuppAccts   TotRetBal  TotRetAccts  TotDisBal   TotDisAccts
 1234         70             2           20          1            0             0
 1111         50             1            0          0            60            1

Essentially a client can be in the Accounts table many times as there can be many accounts per client.

The accounts types will always start with the same characters to begin with however depending on how many of these accounts the number can be anything really and subsequent accounts will always be a deceminal then a number... Eg the first SUP account is simply SUP1, however the next SUP account will be SUP1.1, then SUP1.2 etc...

I have written the following query

SELECT ClientNo, SUM(Balance) AS TotSupBal, COUNT(AccountType) AS TotSuppAccts
FROM Account
WHERE (AccountType LIKE 'SUP1.%') OR (AccountType = 'SUP1')
GROUP BY ClientNo

* The reason there is 2 different WHERE clauses is because I can not just use SUP1% as there are accounts like SUP12 which are not the same as as a SUP1.

This Query works fine, however it only produces a listing for those of the account type of SUP. How can I produce the same sort of output, however across multiple columns for each account type?

I am using Microsoft SQL 2008 R2

PIVOT is what you need >> http://msdn.microsoft.com/en-us/library/ms177410(v=sql.105).aspx

Here is a fully working solution:

WITH Accounts (AccountCategory, ClientNo, Balance) as (
  select 
    case 
        when AccountType like 'SUP%' then 'sup'
        when AccountType like 'RET%' then 'ret'
        when AccountType like 'DIS%' then 'dis' 
    end as AccountCategory,
    ClientNo, 
    Balance
  from Account
)
select * from (
  select ClientNo, sup as TotSupBal, ret as TotRetBal, dis as TotDisBal from Accounts as SourceTable PIVOT (
    SUM(Balance)
    FOR AccountCategory IN ([sup], [ret], [dis])
  ) as pt
) as sums inner join (
  select ClientNo, sup as TotSupAccts, ret as TotRetAccts, dis as TotDisAccts from Accounts as SourceTable PIVOT (
   COUNT(Balance)
   FOR AccountCategory IN ([sup], [ret], [dis])
  ) as pt
) as counts on sums.ClientNo = counts.ClientNo

Try it on SqlFiddle: http://sqlfiddle.com/#!6/d5e91/26

Let me assume that you know what the account types are in advance. In this case, you just want a conditional aggregation sum:

select clientNo,
       sum(case when (AccountType LIKE 'SUP1.%') OR (AccountType = 'SUP1')
                then Balance
            end) as TotSupBal,
       sum(case when (AccountType LIKE 'SUP1.%') OR (AccountType = 'SUP1')
                then 1
                else 0
           end) as TotSupAccts,
       sum(case when left(AccountType, 3) = 'RET'
                then Balance
            end) as TotRetBal,
       sum(case when left(AccountType, 3) = 'RET'
                then 1
                else 0
           end) as TotRetAccts,
       . . .
from account
group by clientNo

I'm not sure what the exact logic is for the other accounts, so I'm just looking at the first three characters.

SELECT
    ClientNo, 
    SUM(Balance) AS TotSupBal,
    COUNT(AccountType) AS TotSuppAccts,
    ret_bal AS TotRetBal,
    total_ret AS TotRetAccts
FROM 
    Account,
    (
        SELECT
            ClientNo c_num,
            SUM(Balance) AS ret_bal,
            COUNT(AccountType) total_ret
        WHERE AccountType LIKE 'RET%'
        GROUP BY ClientNo
    ) Table1RET_type  -- Your name for new table(You create new temporary table for you select) 
WHERE
    ((AccountType LIKE 'SUP1.%') OR (AccountType = 'SUP1'))
    AND Table1RET_type.c_num = ClientNo -- This is called join Table(google it for more info)
GROUP BY ClientNo

Now you have to repeat this logic for all Columns you want to create.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM