Solved

SQL Query to sum amounts, and convert into calendar months

Posted on 2014-03-25
5
207 Views
Last Modified: 2014-04-02
Hi,

I need to create a an SQL query which takes the information from the main "Projects" table, and then uses column "WBS1" to join onto 3 other tables "AP","AR","EX".
The 3 AP,AR,EX tables have the information stored per transaction date.

The requirement is to return the sum(AP+AR+EX) Per WBS1 but for each calendar month.

It is also important that if there has been no transactions for the month , it returns <null> rather than 0

The attached PDF hopefully explains a little more.

thanks in advance
SQL-WBS1.pdf
0
Comment
Question by:supertramp4
  • 2
  • 2
5 Comments
 
LVL 33

Expert Comment

by:ste5an
ID: 39953758
E.g.
DECLARE @A TABLE ( A1 INT, A2 INT );
DECLARE @B TABLE ( B1 INT, B2 DATE, B3 INT );
DECLARE @C TABLE ( C1 INT, C2 DATE, C3 INT );

INSERT  INTO @A
VALUES  ( 1, 1 ),
        ( 2, 20 ),
        ( 3, 300 );

INSERT  INTO @B
VALUES  ( 1, '19000101', 1 ),
        ( 1, '19000201', 2 ),
        ( 1, '19000301', 3 ),
        ( 2, '19000101', 1 ),
        ( 2, '19000101', 2 );

INSERT  INTO @C
VALUES  ( 1, '19000101', 1 ),
        ( 1, '19000401', 40 ),
        ( 3, '19000103', 300 );

WITH    Data
          AS ( SELECT   A.A1 ,
                        A.A2 ,
                        Q.Q2 ,
                        Q.Q3
               FROM     @A A
                        INNER JOIN ( SELECT B1 ,
                                            MONTH(B2) ,
                                            B3
                                     FROM   @B
                                     UNION ALL
                                     SELECT C1 ,
                                            MONTH(C2) ,
                                            C3
                                     FROM   @C
                                   ) Q ( Q1, Q2, Q3 ) ON A.A1 = Q.Q1
             )
    SELECT  *
    FROM    Data PIVOT ( SUM(Q3) FOR Q2 IN ( [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12] ) ) P;

Open in new window

0
 
LVL 69

Accepted Solution

by:
ScottPletcher earned 500 total points
ID: 39954111
/* Data Setup Only, NOT main code */

IF OBJECT_ID('tempdb..#projects') IS NOT NULL
    DROP TABLE #projects
CREATE TABLE #projects (
    WBS1 varchar(30),
    Status varchar(10),
    Reference varchar(30)
    )
INSERT INTO #projects
SELECT 'wbs123', 'Active', 'AQ73' UNION ALL
SELECT 'Wbs456', 'Active', 'ZZ74' UNION ALL
SELECT 'Wbs789', 'inactive', 'WR89'

IF OBJECT_ID('tempdb..#AP') IS NOT NULL
    DROP TABLE #AP
CREATE TABLE #AP (
    WBS1 varchar(30),
    Date datetime,
    Amount money
    )
INSERT INTO #AP
SELECT 'wbs123', '01-jan-2013', £1.00 UNION ALL
SELECT 'Wbs123', '03-mar-2013', £2.00 UNION ALL
SELECT 'Wbs456', '03-mar-2013', £4.56

IF OBJECT_ID('tempdb..#AR') IS NOT NULL
    DROP TABLE #AR
CREATE TABLE #AR (
    WBS1 varchar(30),
    Date datetime,
    Amount money
    )
INSERT INTO #AR
SELECT 'wbs123', '01-jan-2013', £1.00 UNION ALL
SELECT 'Wbs123', '03-mar-2013', £2.00

IF OBJECT_ID('tempdb..#EX') IS NOT NULL
    DROP TABLE #EX
CREATE TABLE #EX (
    WBS1 varchar(30),
    Date datetime,
    Amount money
    )
INSERT INTO #EX
SELECT 'wbs123', '01-Mar-2013', £1.00




-- MAIN CODE BEGINS HERE

DECLARE @start_date datetime
SET @start_date = '20130101' --<<-- set to desired starting date (does not have to be Jan 1)

---------------------------------------------------------------------------------

-- force @start_date to be the first day of the month at midnight
SET @start_date = DATEADD(MONTH, DATEDIFF(MONTH, 0, @start_date), 0)

SELECT
    p.WBS1, p.Reference,
    NULLIF(SUM(CASE WHEN MONTH(dates.Date_Month) = 01 THEN ISNULL(ap.Amount_Month, 0) +
        ISNULL(ar.Amount_Month, 0) + ISNULL(ex.Amount_Month, 0) END), 0) AS Jan,
    NULLIF(SUM(CASE WHEN MONTH(dates.Date_Month) = 02 THEN ISNULL(ap.Amount_Month, 0) +
        ISNULL(ar.Amount_Month, 0) + ISNULL(ex.Amount_Month, 0) END), 0) AS Feb,
    NULLIF(SUM(CASE WHEN MONTH(dates.Date_Month) = 03 THEN ISNULL(ap.Amount_Month, 0) +
        ISNULL(ar.Amount_Month, 0) + ISNULL(ex.Amount_Month, 0) END), 0) AS Mar,
    NULLIF(SUM(CASE WHEN MONTH(dates.Date_Month) = 04 THEN ISNULL(ap.Amount_Month, 0) +
        ISNULL(ar.Amount_Month, 0) + ISNULL(ex.Amount_Month, 0) END), 0) AS Apr,
    NULLIF(SUM(CASE WHEN MONTH(dates.Date_Month) = 05 THEN ISNULL(ap.Amount_Month, 0) +
        ISNULL(ar.Amount_Month, 0) + ISNULL(ex.Amount_Month, 0) END), 0) AS May,
    NULLIF(SUM(CASE WHEN MONTH(dates.Date_Month) = 06 THEN ISNULL(ap.Amount_Month, 0) +
        ISNULL(ar.Amount_Month, 0) + ISNULL(ex.Amount_Month, 0) END), 0) AS Jun,
    NULLIF(SUM(CASE WHEN MONTH(dates.Date_Month) = 07 THEN ISNULL(ap.Amount_Month, 0) +
        ISNULL(ar.Amount_Month, 0) + ISNULL(ex.Amount_Month, 0) END), 0) AS Jul,
    NULLIF(SUM(CASE WHEN MONTH(dates.Date_Month) = 08 THEN ISNULL(ap.Amount_Month, 0) +
        ISNULL(ar.Amount_Month, 0) + ISNULL(ex.Amount_Month, 0) END), 0) AS Aug,
    NULLIF(SUM(CASE WHEN MONTH(dates.Date_Month) = 09 THEN ISNULL(ap.Amount_Month, 0) +
        ISNULL(ar.Amount_Month, 0) + ISNULL(ex.Amount_Month, 0) END), 0) AS Sep,
    NULLIF(SUM(CASE WHEN MONTH(dates.Date_Month) = 10 THEN ISNULL(ap.Amount_Month, 0) +
        ISNULL(ar.Amount_Month, 0) + ISNULL(ex.Amount_Month, 0) END), 0) AS Oct,
    NULLIF(SUM(CASE WHEN MONTH(dates.Date_Month) = 11 THEN ISNULL(ap.Amount_Month, 0) +
        ISNULL(ar.Amount_Month, 0) + ISNULL(ex.Amount_Month, 0) END), 0) AS Nov,
    NULLIF(SUM(CASE WHEN MONTH(dates.Date_Month) = 12 THEN ISNULL(ap.Amount_Month, 0) +
        ISNULL(ar.Amount_Month, 0) + ISNULL(ex.Amount_Month, 0) END), 0) AS Dec
FROM #projects p
CROSS JOIN (
    --DECLARE @start_date datetime SET @start_date = '20130101'
    SELECT DATEADD(MONTH, month_counter, @start_date) AS Date_Month
    FROM (
        SELECT 00 AS month_counter UNION ALL SELECT 01 UNION ALL SELECT 02 UNION ALL SELECT 03 UNION ALL
        SELECT 04 UNION ALL SELECT 05 UNION ALL SELECT 06 UNION ALL SELECT 07 UNION ALL
        SELECT 08 UNION ALL SELECT 09 UNION ALL SELECT 10 UNION ALL SELECT 11
    ) AS month_counters
) AS dates
LEFT OUTER JOIN (
    --DECLARE @start_date datetime SET @start_date = '20130101'
    SELECT
        WBS1,
        DATEADD(MONTH, DATEDIFF(MONTH, 0, Date), 0) AS Date_Month,
        SUM(Amount) AS Amount_Month
    FROM #AP
    WHERE
        Date >= @start_date AND
        Date < DATEADD(MONTH, 12, @start_date)
    GROUP BY
        WBS1, DATEADD(MONTH, DATEDIFF(MONTH, 0, Date), 0)
) AS ap ON
    ap.WBS1 = p.WBS1 AND
    ap.Date_Month = dates.Date_Month
LEFT OUTER JOIN (
    --DECLARE @start_date datetime SET @start_date = '20130101'
    SELECT
        WBS1,
        DATEADD(MONTH, DATEDIFF(MONTH, 0, Date), 0) AS Date_Month,
        SUM(Amount) AS Amount_Month
    FROM #AR
    WHERE
        Date >= @start_date AND
        Date < DATEADD(MONTH, 12, @start_date)
    GROUP BY
        WBS1, DATEADD(MONTH, DATEDIFF(MONTH, 0, Date), 0)
) AS ar ON
    ar.WBS1 = p.WBS1 AND
    ar.Date_Month = dates.Date_Month
LEFT OUTER JOIN (
    SELECT
        WBS1,
        DATEADD(MONTH, DATEDIFF(MONTH, 0, Date), 0) AS Date_Month,
        SUM(Amount) AS Amount_Month
    FROM #EX
    WHERE
        Date >= @start_date AND
        Date < DATEADD(MONTH, 12, @start_date)
    GROUP BY
        WBS1, DATEADD(MONTH, DATEDIFF(MONTH, 0, Date), 0)
) AS ex ON
    ex.WBS1 = p.WBS1 AND
    ex.Date_Month = dates.Date_Month
WHERE
    p.Status = 'Active'
GROUP BY
    p.WBS1, p.Reference
0
 

Author Comment

by:supertramp4
ID: 39955309
hi both,

thanks for the examples, I am out of the office today, but will try as soon as I can.
0
 

Author Closing Comment

by:supertramp4
ID: 39971598
Nice solution, and this is now working will in our system
0
 
LVL 33

Expert Comment

by:ste5an
ID: 39971920
My solution is shorter...

WITH    Data
          AS ( SELECT   A.WBS1 ,
                        A.Reference ,
                        Q.MonthDate ,
                        Q.Amount
               FROM     #Projects A
                        INNER JOIN ( SELECT WBS1 ,
                                            MONTH([Date]) MonthDate ,
                                            Amount
                                     FROM   #AP
                                     UNION ALL
                                     SELECT WBS1 ,
                                            MONTH([Date]) MonthDate ,
                                            Amount
                                     FROM   #AR
                                     UNION ALL
                                     SELECT WBS1 ,
                                            MONTH([Date]) MonthDate ,
                                            Amount
                                     FROM   #EX
                                   ) Q ON A.WBS1 = Q.WBS1
               WHERE    A.[Status] = 'Active'
             )
    SELECT  *
    FROM    Data PIVOT ( SUM(Amount) FOR MonthDate IN ( [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12] ) ) P;

Open in new window


Using one more CTE for clarity:

WITH    RawData
          AS ( SELECT   WBS1 ,
                        MONTH([Date]) MonthDate ,
                        Amount
               FROM     #AP
               UNION ALL
               SELECT   WBS1 ,
                        MONTH([Date]) MonthDate ,
                        Amount
               FROM     #AR
               UNION ALL
               SELECT   WBS1 ,
                        MONTH([Date]) MonthDate ,
                        Amount
               FROM     #EX
             ),
        JoinedData
          AS ( SELECT   A.WBS1 ,
                        A.Reference ,
                        Q.MonthDate ,
                        Q.Amount
               FROM     #Projects A
                        INNER JOIN RawData Q ON A.WBS1 = Q.WBS1
               WHERE    A.[Status] = 'Active'
             )
    SELECT  *
    FROM    JoinedData PIVOT ( SUM(Amount) FOR MonthDate IN ( [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12] ) ) P;

Open in new window

0

Featured Post

Comprehensive Backup Solutions for Microsoft

Acronis protects the complete Microsoft technology stack: Windows Server, Windows PC, laptop and Surface data; Microsoft business applications; Microsoft Hyper-V; Azure VMs; Microsoft Windows Server 2016; Microsoft Exchange 2016 and SQL Server 2016.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
SQL Select Statement 2 21
TSQL DateADD update Question 4 29
Help with Sorting Full Text results 2 14
Help Parsing a String with SQL Syntax 23 28
Introduction In my previous article (http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/SSIS/A_9150-Loading-XML-Using-SSIS.html) I showed you how the XML Source component can be used to load XML files into a SQL Server database, us…
This article shows gives you an overview on SQL Server 2016 row level security. You will also get to know the usages of row-level-security and how it works
Familiarize people with the process of retrieving data from SQL Server using an Access pass-thru query. Microsoft Access is a very powerful client/server development tool. One of the ways that you can retrieve data from a SQL Server is by using a pa…
Viewers will learn how the fundamental information of how to create a table.

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now