Shrout1
Shrout1

Reputation: 2607

Joining Summed data that has nulls - SQL Server

How do I retain the Acct_Name field where appropriate when summing the data below by the Amount column and grouping by the Line_Num field? The "Null" values in Line_Num column cause a problem in the grouping terms when the account name is added. Accounts C and D both have Null values in Line_Num. If I add Acct_Name to the group by clause, I lose the ability to sum the values only by the Line_Num field.

I am attempting to sum lines of accounting and group based on the line number. The null data isn't my doing, unfortunately it's just the data set I was handed.

Original data:

Acct_Name   ID      Line_Num   Amount
Acct A      1       1_01       100.0000
Acct A      1       1_01       -50.0000
Acct A      1       1_02       75.0000
Acct A      1       _02        125.0000
Acct B      2       2_01       200.0000
Acct B      2       2_01       50.0000
Acct B      2       2_02       25.0000
Acct C      3       3_01       75.0000
Acct C      3       3_02       50.0000
Acct C      3       3_03       -25.0000
Acct C      3       Null       65.0000
Acct D      4       Null       300.0000
Acct D      4       _02        100.0000
Acct D      4       Null       -50.0000
Acct D      4       Null       75.0000

If the Line_Num value is null, that line is allowed to be aggregated with the other null values. It will show up in reports as being unaccounted for and it can be dealt with appropriately.

Ideal processed data set:

Amount  Line_Num Acct_Name
390.00  Null     Null
225.00  _02      Null
50.00   1_01     Acct A
75.00   1_02     Acct A
250.00  2_01     Acct B
25.00   2_02     Acct B
75.00   3_01     Acct C
50.00   3_02     Acct C
-25.00  3_03     Acct C

Here are the following queries I have used:

Select SUM(Amount), Line_Num
FROM dbo.tblRawData
Group By Line_Num

This query works just fine, but it does not include the account name in any of the aggregated fields. I need the account name in the fields that did not contain null values.

Select SUM(Amount), Line_Num, Acct_Name
FROM dbo.tblRawData
Group By Line_Num, Acct_Name

This query includes the account name, but it ends up grouping based on Account Name and not just Line_Num.

Select *
From dbo.tblRawData a
Inner Join dbo.tblRawData b On (a.Line_Num = b.Line_Num)
(SELECT SUM(CAST(Amount as money)) as Amount, Line_Num
FROM dbo.tblRawData
GROUP BY Line_Num)

This inner join is intended to join only those lines that are equivalent on the Line Num, but I am receiving a cartesian result set. Clearly I have not written this join correctly or I am using the incorrect command.

Here is the query that can be used to build the same schema that I am using:

CREATE TABLE [dbo].[tblRawData](
[Acct_Name] [nvarchar](50) NULL,
[ID] [nvarchar](50) NULL,
[Line_Num] [nvarchar] (50),
[Amount] [money]
) ON [PRIMARY]

GO

insert into dbo.tblRawData values ('Acct A', '1', '1_01', '100')
insert into dbo.tblRawData values ('Acct A', '1', '1_01', '-50')
insert into dbo.tblRawData values ('Acct A', '1', '1_02', '75')
insert into dbo.tblRawData values ('Acct A', '1', '_02', '125')
insert into dbo.tblRawData values ('Acct B', '2', '2_01', '200')
insert into dbo.tblRawData values ('Acct B', '2', '2_01', '50')
insert into dbo.tblRawData values ('Acct B', '2', '2_02', '25')
insert into dbo.tblRawData values ('Acct C', '3', '3_01', '75')
insert into dbo.tblRawData values ('Acct C', '3', '3_02', '50')
insert into dbo.tblRawData values ('Acct C', '3', '3_03', '-25')
insert into dbo.tblRawData values ('Acct C', '3', '', '65')
insert into dbo.tblRawData values ('Acct D', '4', '', '300')
insert into dbo.tblRawData values ('Acct D', '4', '_02', '100')
insert into dbo.tblRawData values ('Acct D', '4', '', '-50')
insert into dbo.tblRawData values ('Acct D', '4', '', '75')

P.S. SQL Fiddle appears to be inaccessible at the moment (might be on my end, don't know)

Edit

Take a look at the following code and holler if it seems that there are blatant flaws in trying to accomplish my goal. I'd prefer for Acct_Name to remain null if Line_Item doesn't match up, but perhaps I can sort that out.

IF (SELECT object_id('TempDB..#temp4')) IS NOT NULL
BEGIN
    DROP TABLE #temp4
END

SELECT SUM(CAST(Amount as money)) as Amount, Line_Num INTO #temp4
FROM dbo.tblRawData
GROUP BY Line_Num

Select * from #temp4

Select MAX(a.Acct_Name) as Acct_Name, MAX(b.Line_Num) as Line_Num, MAX(b.Amount) as Amount
From dbo.tblRawData a
Inner Join #temp4 b On (a.Line_Num = b.Line_Num)
Group By b.Line_Num

Results:

Acct_Name  Line_Num Amount
Acct D     Null     390.00
Acct D     _02      225.00
Acct A     1_01     50.00
Acct A     1_02     75.00
Acct B     2_01     250.00
Acct B     2_02     25.00
Acct C     3_01     75.00
Acct C     3_02     50.00
Acct C     3_03     -25.00

Upvotes: 2

Views: 105

Answers (1)

Lamak
Lamak

Reputation: 70638

Here you go:

;WITH CTE AS
(
    SELECT  Line_Num, 
            SUM(Amount) Amount,
            MIN(Acct_Name) MinAcct_Name,
            MAX(Acct_Name) MaxAcct_Name
    FROM tblRawData
    GROUP BY Line_Num
)
SELECT  Amount,
        Line_Num,
        CASE WHEN Line_Num IS NULL 
        OR MinAcct_Name <> MaxAcct_Name THEN NULL
        ELSE MinAcct_Name END Acct_Name
FROM CTE

Upvotes: 2

Related Questions