On 08-Jan-2015 08:51 -0600, Gqcy wrote:
I need to get length and width out of our item master via SQL..
database field defined: Packed 11,4 (IXXXX)
CREATE TABLE ...
( ...
, IXXXX DECIMAL(11, 4) /* 9999999.9999 */
)
old, <charles barkley>TERRIBLE</cb> desire usage of field:
width: positions 1-05, 3 decimal positions
length: positions 6-11, 3 decimal positions
Width declared as 05S03 [NUMERIC(5, 3)] and will be described with
the letter 'w' representing the numeric digits: WW.www
Length declared as 06S03 [NUMERIC(6, 3)] and will be described with
the letter 'l' representing the numeric digits: LLL.lll
scale line: ....+....1. /* positions 1 thru 11 */
as stored:: WWwwwLLLlll /* values: WW.www and LLL.lll */
Note: the storage does not include decimal separator
good ole RPGII code to do this:
C IXXXX MULT 10000 IXXXX0 11 0
The effect is that the 11P00 variable named IXXXX0=WWwwwLLLlll
C MOVEL IXXXX0 IWIDE 5 3
The effect is that the 05P03 variable named IWIDE=WW.www
C MOVE IXXXX0 ILENG 6 3
The effect is that the 06P03 variable named ILENG=LLL.lll
or, we also did...
D ds
D IXXX4 11 4
D Width 5 3 overlay(IXXX4:1)
D Length 6 3 overlay(IXXX4:6)
C IXXX4 = IXXXX;
The effect is that the 05S03 variable named Width=WW.www and the
06S03 variable named Length=LLL.lll
Thus with both the RPG and RPGIV, the separate data items stored
combined in the one field IXXXX is properly split into the two separate
variables within the program.
when I try the following:
select substr((IXXXX * 10000), 1, 5) as width
, substr((IXXXX * 10000), 6 ,6) as length
, IPROD
from ......
For best\consistent results, the expression (IXXXX*10000) should be
cast into the desired numeric type before using the SUBSTR scalar; the
implicit casting of that expression is to the numeric type DECIMAL(16,4)
and per implicit casting to character [effectively an implied CHAR()
casting scalar] of that result is a *left-justified* result. That means
if the value of the /width/ portion of IXXXX value is less than 10 or
the /length/ portion of the IXXXX value is less than 100, the SUBSTR()
will produce *incorrect* results.
That casting [noted above] is per the literal\constant value 10000
being typed as INT, but per multiplication with Decimal typed column, a
temporary copy of the INT is made into a P(length('10000'),0), thus we
have ["P(p,s)" implies Packed decimal of precision=p and scale=s]:
P(11,4)*P(5,0)
That means p=11, s=4, p'=5, s'=0 for the rule that the "precision of
the result of multiplication is min(mp,p+p') and the scale is
min(ms,s+s')" where mp is maximum precision and ms is maximum scale
[which are likely default of 31 per the Decimal Result Options
(DECRESULT) specification]. Thus the typing of the final result is
P(11+5,4) or P(16,4).
<
http://www.ibm.com/support/knowledgecenter/api/content/ssw_ibm_i_71/db2/rbafzintdecoper.htm>
_Integer and decimal operands_
<
http://www.ibm.com/support/knowledgecenter/api/content/ssw_ibm_i_71/db2/rbafzdecarithmetic.htm>
_Decimal arithmetic in SQL_
I get my length and width as whole numbers, but when I try to push
the math any further (by multiplying by .001), I get zeros in my
fields...
I know my penitence will be great for this...
Skip the arithmetic altogether, and obtain the required data from the
character representation of the number.
For the column IXXXX defined as DECIMAL(11, 4), the effect of the
expression DIGITS(IXXXX)='WWwwwLLLlll'; the same of DECIMAL(11,X) and
NUMERIC(11,X) as the DIGITS casting scalar returns just the digits
without any decimal separator or sign.
Thus the following obtains the whole\integer values as a string:
select substr(DIGITS(IXXXX), 1, 5) as width
, substr(DIGITS(IXXXX), 6 ,6) as length
...
To obtain the decimal values as a string with precision:
select insert(left (DIGITS(IXXXX), 5), 3, 0, '.') as width
, insert(right(DIGITS(IXXXX), 6), 4, 0, '.') as length
...
To obtain the decimal values as numeric with a precision, then one of
the following [where the first example establishes precision implicitly
according to the rules for the multiplication, but best to explicitly
specify what is desired]:
select dec(substr(DIGITS(IXXXX), 1, 5)) * .001 as width
, dec(substr(DIGITS(IXXXX), 6 ,6)) * .001 as length
/* note: the DEC casting scalar defaults to P(5, 0) */
...
select dec(insert(left (DIGITS(IXXXX), 5), 3, 0, '.'), 5, 3) as width
, dec(insert(right(DIGITS(IXXXX), 6), 4, 0, '.'), 6, 3) as length
...
As an Amazon Associate we earn from qualifying purchases.