Question

First, I'm not sure the title adequetely describes what I am trying to achive - so please ammend as you see fit.

I have a table in an SQL database which records budget allocations and transfers.

Each allocation and transfer is recorded against a combination of two details - the year_ID and program_ID. Allocations can come from nowhere or from other year_id & program_id combinations - these are the transfers.

For example, year_ID 1 & program_ID 2 was allocated $1000, then year_ID 1 & program_ID 2 transfered $100 to year_ID 2 & program_id 2.

This is stored in the database like

From_year_ID  From_program_ID  To_year_ID   To_program_ID    Budget
null          null             1            2                1000
1             2                2            2                100    

The query needs to summarise these budget allocations based on the year_id + program_id combination, so the results would display:

year_ID   program_ID    Budget_Allocations    Budget_Transfers
1         2             1000                  100
2         2             100                   0

I've spent two days trying to put this query together and am officially stuck - could someone help me out or point me in the right direction? I've tried what feels like every combination of left, right, inner, union joins, with etc - but haven't got the outcome I'm looking for.

Here is a sqlfiddle with sample data: http://sqlfiddle.com/#!3/9c1ec/1/0 and one of the queries that doesnt quite work.

Was it helpful?

Solution

I would sum the Budget by Program_ID and Year_ID in some CTEs and join those to the Program and Year tables to avoid summing Budget values more than once.

WITH
  bt AS
    (SELECT
       To_Year_ID AS Year_ID,
       To_Program_ID AS Program_ID,
       SUM(Budget) AS Budget_Allocation
     FROM T_Budget
     GROUP BY
       To_Year_ID,
       To_Program_ID),
  bf AS
    (SELECT
       From_Year_ID AS Year_ID,
       From_Program_ID AS Program_ID,
       SUM(Budget) AS Budget_Transfer
     FROM T_Budget
     GROUP BY
       From_Year_ID,
       From_Program_ID)

SELECT
  y.Year_ID,
  p.Program_id,
  bt.Budget_Allocation,
  bf.Budget_Transfer,
  y.Short_Name + ' ' + p.Short_Name AS Year_Program,
  isnull(bt.Budget_Allocation,0) -
     isnull(bf.Budget_Transfer,0)AS Budget_Balance
FROM T_Programs p
  CROSS JOIN T_Years y
  INNER JOIN bt
    ON bt.Program_ID = p.Program_ID 
    AND bt.Year_ID = y.Year_ID
  LEFT JOIN bf
    ON bf.Program_ID = p.Program_ID 
    AND bf.Year_ID = y.Year_ID
ORDER BY
  y.Year_ID,
  p.Program_ID

http://sqlfiddle.com/#!3/9c1ec/13

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top