Question

To start: I am querying a DB2 server built into the IBM i System package from Excel 2007 using "From Microsoft Query" and straight-up SQL. It is a financial database.

The DB is structured such that account #s are split up into 8 integer fields for fund, division, department, activity 1, activity 2, element 1, element 2, and object. In order to make query results readable I have concatenated them with the following code:

select 
  right(trim(trailing from (concat('00',cast(T1."GMFUND" as Char(8))))),3)||'-'
||right(trim(trailing from (concat('00',cast(t1."GMDPT" as Char(8))))),2) 
||right(trim(trailing from (concat('00',cast(T1."GMDIV" as Char(8))))),2) ||'-'
||right(trim(trailing from (concat('00',cast(T1."GMSTAB" as Char(8))))),2)
||right(trim(trailing from (concat('00',cast(T1."GMSTAS" as Char(8))))),1)||'.'
||right(trim(trailing from (concat('00',cast(T1."GMELM1" as Char(8))))),1)
||right(trim(trailing from (concat('00',cast(T1."GMELM2" as Char(8))))),1)||'-'
||right(trim(trailing from (concat('00',cast(T1."GMOBJ" as Char(8))))),2)
  as AJAccount

It's a bit difficult to read, so I'll explain: For each field I am concatenating '00' to each # typecast as an 8-char string (to add leading zeroes), then trimming the trailing blank spaces (from the typecast conversion), and finally grabbing the correct # of digits for each using right(). That ends up making up a single acct # which we use day-to-day in the following format:

000-0000-000.00-00

Now here comes the more complicated part. I need to sum a calculated field for debits and credits, defined by the following:

IFNULL(T1."GMDAMT",0)-IFNULL(T1."GMCAMT",0) as Trans_Total

But that isn't summed yet. And that's where I run into my problem. When I query those two fields I get accurate results for each and every transaction in the DB, labeled w/ acct #s. But when I attempt to enclose the [debits - credits] field in a SUM() aggregate function and group by 'AJAccount' my query throws an error.

The error points to the following section of my concatenated acct # field:

right(trim (trailing from (concat('00',cast(T1."GMOBJ" as Char(8))))),2)

Specifically it highlights "GMOBJ" as the source of the error. But without the SUM() function, the code runs just fine, producing results that look like the following:

001-0000-243.00-00  |  166898.00
001-0000-244.00-00  | -166898.00    
161-0000-243.00-00  |    3000.00     
161-0000-244.00-00  |   -3000.00    
470-0000-243.00-00  |    4999.00     
470-0000-244.00-00  |   -4999.00    
490-0000-243.00-00  |    1000.00     
490-0000-244.00-00  |   -1000.00

This isn't even the half of what I really need to do (because the transaction data is split off into 4 different tables by transaction type that I will eventually need to JOIN on...but that's another task). But until I get this working I am at a dead stop.

This is the whole block of code:

select 
    right(trim(trailing from (concat('00',cast(T1."GMFUND" as Char(8))))),3)||'-'
  ||right(trim(trailing from (concat('00',cast(t1."GMDPT" as Char(8))))),2) 
  ||right(trim(trailing from (concat('00',cast(T1."GMDIV" as Char(8))))),2) ||'-'
  ||right(trim(trailing from (concat('00',cast(T1."GMSTAB" as Char(8))))),2)
  ||right(trim(trailing from (concat('00',cast(T1."GMSTAS" as Char(8))))),1)||'.'
  ||right(trim(trailing from (concat('00',cast(T1."GMELM1" as Char(8))))),1)
  ||right(trim(trailing from (concat('00',cast(T1."GMELM2" as Char(8))))),1)||'-'
  ||right(trim(trailing from (concat('00',cast(T1."GMOBJ" as Char(8))))),2)
      as AJAccount,
  SUM(IFNULL(T1."GMDAMT",0)-IFNULL(T1."GMCAMT",0)) as Trans_Total
from "HTEDTA"."GM310AP" T1
where T1."GMAPYR" = 2014
group by 'AJAccount'

I thought maybe I typo'd or something, so I did the following easier query:

select 
T1."GMFUND",
SUM(IFNULL(T1."GMDAMT",0)-IFNULL(T1."GMCAMT",0)) as Trans_Total
from "HTEDTA"."GM310AP" T1
where T1."GMAPYR" = 2014 and T1."GMAPMO" between 1 and 4
group by T1."GMFUND"
order by T1."GMFUND"

and it ran just fine, producing the following results:

  1  |  20090901.49  
111  |     32635.15  
114  |         0.00  
115  |         0.00  
131  |      5916.66

So I suspect I am lacking knowledge about calculated fields and SUM(). Can someone enlighten me?

Was it helpful?

Solution

Am assuming the error is SQL0206 - Column or global variable AJAccount not found.

If true, the problem is that the GROUP BY clause is looking for a column in the database table, not a derived column in the SELECT clause. Try putting the entire derived column in your GROUP BY:

select...
where...
group by right(trim (trailing from (concat('00',cast(T1."GMFUND" as Char(8))))),3) || '-' || right(trim (trailing from (concat('00',cast(t1."GMDPT" as Char(8))))),2) || right(trim (trailing from (concat('00',cast(T1."GMDIV" as Char(8))))),2) || '-' ||  right(trim (trailing from (concat('00',cast(T1."GMSTAB" as Char(8))))),2) || right(trim (trailing from (concat('00',cast(T1."GMSTAS" as Char(8))))),1) || '.' || right(trim (trailing from (concat('00',cast(T1."GMELM1" as Char(8))))),1) || 
right(trim (trailing from (concat('00',cast(T1."GMELM2" as Char(8))))),1) || '-' || right(trim (trailing from (concat('00',cast(T1."GMOBJ" as Char(8))))),2) 
order by 1

OTHER TIPS

A simplified example using a common-table-expression:

WITH gm310ap AS (SELECT 
    RIGHT('00'||DIGITS(gmfund),3) || '-' ||
    RIGHT('0'||DIGITS(gmdpt),2) || 
    RIGHT('0'||DIGITS(gmdiv),2) || '-' || 
    RIGHT('0'||DIGITS(gmstab),2) ||
    RIGHT(DIGITS(gmstas),1) || '.' ||
    RIGHT(DIGITS(gmelm1),1) ||
    RIGHT(DIGITS(gmelm2),1) || '-' ||
    RIGHT('0'||DIGITS(gmobj),2) AS AJAccount,
    COALESCE(gmdamt,0) - COALESCE(gmcamt,0) AS Trans_Total
FROM "HTEDTA"."GM310AP"
WHERE gmapyr = 2014)
SELECT AJAccount, SUM(Trans_Total)
FROM gm310ap
GROUP BY AJAccount

Documentation for the scalar functions:

If the code you have shown is exactly what you ran, then your query has a simple syntax issue. You said GROUP BY 'AJAccount' which is a string literal. Double quotes ("AJAccount") would make it a case sensitive column reference. However, when you said as AJAaccount you did not use double quotes, so the name is not case sensitive and so you do not need the quotes in the GROUP BY.

Assuming your columns are at least as long as the portions you are trying to extract, I would try the following query:

SELECT (  RIGHT(DIGITS(gmfund),3) ||'-' 
       || RIGHT(DIGITS(gmdpt),2)
       || RIGHT(DIGITS(gmdiv),2) || '-'
       || RIGHT(DIGITS(gmstab),2)
       || RIGHT(DIGITS(gmstas),1) || '.'
       || RIGHT(DIGITS(gmelm1),1)
       || RIGHT(DIGITS(gmelm2),1) || '-'
       || RIGHT('0'||DIGITS(gmobj),2)
       ) as AJAccount,
       sum(gmdamt) - sum(gmcamt) AS Trans_Total
    FROM "HTEDTA"."GM310AP"
    WHERE gmapyr = 2014
    GROUP BY AJAccount

My guess is that there may be plenty of other queries that would use this concatenated account number. If this is the case, you might consider creating a view to store this logic for use elsewhere, perhaps like this:

CREATE OR REPLACE VIEW HTEDTA.GM310AP_AC
  SELECT (  RIGHT(DIGITS(gmfund),3) ||'-' 
         || RIGHT(DIGITS(gmdpt),2)
         || RIGHT(DIGITS(gmdiv),2) || '-'
         || RIGHT(DIGITS(gmstab),2)
         || RIGHT(DIGITS(gmstas),1) || '.'
         || RIGHT(DIGITS(gmelm1),1)
         || RIGHT(DIGITS(gmelm2),1) || '-'
         || RIGHT('0'||DIGITS(gmobj),2)
         ) as AJAccount,
         gmdamt,
         gmcamt      -- include any other useful columns
    FROM HTEDTA.GM310AP

Once that has been created, you can write queries such as

SELECT AJAccount,
       SUM( IFNULL(gmdamt,0) - IFNULL(gmcamt) ) as Trans_Total
  FROM HTEDTA.GM310AP_AC
  GROUP BY AJAccount
  ORDER BY AJAccount

Or

WITH Q AS
( SELECT AJAccount,
         SUM(gmdamt) as TotD,
         SUM(gmcamt) as TotC
  FROM HTEDTA.GM310AP_AC
  GROUP BY AJAccount
)
SELECT AJAccount, 
       TotD - TotC   as Trans_Total
  FROM Q
  ORDER BY AJAccount

P.S. You only need the IFNULL if those columns are nullable. This is traditionally rather rare on DB2 for i, so if you check this, you might simplify things a bit more for yourself.

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