As background, we are currently using Lotus Approach as our job schedule database. Out of fear that one day it'll cease working with newer versions of Windows, I've been searching for an alternative that isn't terribly dissimilar from Approach. One of the features in Approach that has been wonderful is that calculated fields are stored in the front end and has full access to all tables in the database, as well as other calculated fields without having to link them to forms, reports, or each other. I have yet to find a program that handles calculated fields in a similar manner, so I've moved to using queries in Access to beginning building these calculated fields (around 200 formulas).
That said, I have 4 tables and 3 queries, but I'm hitting a wall with one of the queries. In the query that's giving me the error, I think I've determined the problem has to do with 1 switch statement (AUDIT_JTD_EARNED_REV) as there are 3 other formulas that rely on this calculation and if I delete one of these (not all of them), then the query will run.
I have not used Access before in any meaningful way, so if there is a better way of doing it, then I'm all ears. Below are the 3 queries I'm using and the error is occurring in the Audit Calc query.
Audit Calc
SELECT Book.job_id,
(
Book.jtd_ti_cost - Book.audit_jtd_ti_cost + Book.jtd_eq_credit + Book.sdp_profit ) AS AUDIT_FCST_PROFIT_ADJ,
Book.book_jtd_cost - audit_fcst_profit_adj + ICalc.ic_audit_jtd_profit_adj
AS
AUDIT_JTD_COST,
Switch(Book.stat_cd = 'C', Book.jtd_gross_bill + Book.accrued_billing,
( Book.stat_cd = 'I'
AND
audit_jtd_cost + audit_fcst_profit >
Book.book_contract_amt * audit_pct_cmpl )
OR (
Book.stat_cd = 'A'
AND Book.job_type <> '2'
AND audit_pct_cmpl >= 0.2 ), Round(Book.book_contract_amt * audit_pct_cmpl, 2),
Book.stat_cd = 'A'
AND Book.job_type = '1'
AND audit_pct_cmpl < 0.2, audit_jtd_cost, true,
audit_jtd_cost + audit_fcst_profit)
AS AUDIT_JTD_EARNED_REV,
Book.book_contract_amt - audit_fcst_profit
AS AUDIT_FCST_COST,
Switch(Book.book_contract_amt < 1, 1, Book.job_type = 2,
Book.jtd_gross_bill - Book.accrued_billing / Book.book_contract_amt, true,
audit_jtd_cost / audit_fcst_cost)
AS AUDIT_PCT_CMPL,
Nz(Book.fcst_job_profit)
+ audit_fcst_profit_adj
+ Nz(ICalc.ic_audit_fcst_profit)
AS AUDIT_FCST_PROFIT,
Round(audit_jtd_earned_rev - Nz(Book.prior_adt_rev), 2)
AS AUDIT_YTD_EARNED_REV,
audit_jtd_cost + audit_addl_loss - Nz(Book.prior_adt_cost)
AS AUDIT_YTD_COST,
audit_ytd_earned_rev - audit_ytd_cost
AS AUDIT_YTD_EARNED_PROFIT,
Switch(Book.prime_job_id IS NULL
OR ( Nz(Book.fcst_job_profit, 0) - Nz(ICBook.fcst_job_profit, 0) ) > 0
OR Book.stat_cd <> 'A'
OR
( Book.book_contract_amt - audit_fcst_cost ) >= 0, 0, true,
audit_fcst_profit - audit_jtd_cost + audit_jtd_earned_rev)
AS AUDIT_ADDL_LOSS,
Iif(Book.stat_cd <> "a", 0, audit_fcst_cost - audit_jtd_cost)
AS
AUDIT_FCST_COST_TO_CMPL,
audit_fcst_profit / Iif(Book.job_type = 2,
Book.book_contract_amt, audit_fcst_cost)
AS AUDIT_PROFIT_PCT,
audit_jtd_earned_rev - audit_jtd_cost + audit_addl_loss
AS
AUDIT_JTD_EARNED_PROFIT,
audit_jtd_earned_rev - Book.jtd_gross_bill - Book.accrued_billing + Nz(Book.jtd_ret_amt) AS AUDIT_OVER_UNDER_BILLING
FROM ([book calc] AS Book
LEFT JOIN [book calc] AS ICBook
ON Book.job_id = ICBook.prime_job_id)
LEFT JOIN [interco calc] AS ICalc
ON Book.job_id = ICalc.prime_job_id;
Interco Calc
SELECT [book calc].prime_job_id
AS PRIME_JOB_ID,
[book calc].job_id
AS SUB_JOB_ID,
[book calc].jtd_ti_cost - [book calc].audit_jtd_ti_cost +
[book calc].jtd_eq_credit + [book calc].sdp_profit
AS IC_AUDIT_FCST_PROFIT_ADJ,
[book calc].fcst_job_profit
+ ic_audit_fcst_profit_adj
AS IC_AUDIT_FCST_PROFIT,
Round([book calc].jtd_mat_cost
+ [book calc].jtd_sub_cost
+ [book calc].jtd_oth_cost
+ [book calc].jtd_gl_cost
+ [book calc].jtd_eq_cost
+ [book calc].jtd_labor_cost
+ [book calc].accrued_cost
+ Nz([book calc].prior_adt_ti)
+ [book calc].audit_ytd_ti_cost - Nz([book calc].prior_eq_credit) -
[book calc].ytd_eq_credit + [book calc].jtd_sdp_cost -
[book calc].sdp_profit, 2)
AS IC_AUDIT_JTD_COST,
ic_audit_jtd_cost - ( [book calc].jtd_gross_bill
+ [book calc].accrued_billing )
AS IC_AUDIT_JTD_PROFIT_ADJ,
Iif([book calc].book_contract_amt < 1, 1,
Iif([book calc].job_type = 2, ( [book calc].gross_bill
+ [book calc].accrued_billing ) /
[book calc].book_contract_amt, ic_audit_jtd_cost / ic_audit_fcst_cost)) AS IC_AUDIT_PCT_CMPL,
[book calc].book_contract_amt - ic_audit_fcst_profit
AS IC_AUDIT_FCST_COST
FROM [book calc]
WHERE ( [book calc].prime_job_id ) IS NOT NULL;
And finally Book Calc
SELECT fsjob.*,
eq_aed.eq_aed_prem
AS EQ_AED_PREM,
eq_aed.eq_aed_chrg
AS EQ_AED_CHRG,
Nz(fsjob.gross_bill)
+ Nz(fsjob.prior_gross_bill)
+ Nz(fsjob.prior_accr_bill)
AS JTD_GROSS_BILL,
Round(Nz(fsjob.sc_cost) + Nz(fsjob.prior_sc_cost), 2)
AS JTD_SUB_COST,
Nz(fsjob.labor_cost)
+ Nz(fsjob.prior_labor_cost)
AS JTD_LABOR_COST,
Nz(fsjob.oth_cost)
+ Nz(fsjob.prior_oth_cost)
AS JTD_OTH_COST,
Nz(fsjob.mat_cost)
+ Nz(fsjob.prior_mat_cost)
AS JTD_MAT_COST,
Nz(fsjob.eq_cost) + Nz(fsjob.prior_eq_cost)
AS JTD_EQ_COST,
Nz(fsjob.gl_cost) + Nz(fsjob.prior_gl_cost)
AS JTD_GL_COST,
Nz(fsjob.ti_cost) + Nz(fsjob.prior_ti_cost)
AS JTD_TI_COST,
Iif(( fsjob.sdp_cd = 'SDP'
AND fsjob.stat_cd = 'I' )
OR ( fsjob.sdp_cd = 'SDP'
AND jtd_gross_bill > 0
AND fsjob.stat_cd = 'A'
AND jtd_sub_cost > 0 ), Round(variable.sdp_pct *
Nz(fsjob.fcst_sc_cost), 2), 0)
AS
JTD_SDP_COST,
Switch(fsjob.stat_cd = 'I', Nz(fsjob.contract_amt, 0) - jtd_gross_bill, true, Nz(fsjob.accr_bill_adj, 0))
AS ACCRUED_BILLING,
Switch(fsjob.stat_cd = 'C', jtd_gross_bill + accrued_billing, true, Nz(fsjob.contract_amt, 0))
AS BOOK_CONTRACT_AMT,
Iif(fsjob.stat_cd = 'I', Round(
book_contract_amt - Nz(fsjob.fcst_job_profit)
- jtd_sub_cost + jtd_labor_cost + jtd_oth_cost + jtd_mat_cost + jtd_eq_cost + jtd_gl_cost + jtd_ti_cost + jtd_sdp_cost, 2), Nz(fsjob.accr_cost_adj))
AS ACCRUED_COST,
Round(jtd_sub_cost + jtd_labor_cost + jtd_oth_cost
+ jtd_mat_cost + jtd_eq_cost + jtd_gl_cost
+ jtd_ti_cost + jtd_sdp_cost + accrued_cost, 2)
AS BOOK_JTD_COST,
Round(book_contract_amt - Nz(fsjob.fcst_job_profit), 2)
AS BOOK_FCST_COST,
Iif(fsjob.stat_cd = 'C'
OR
book_contract_amt < 1, 1,
Iif(fsjob.job_type = 2, ( accrued_billing + jtd_gross_bill ) / book_contract_amt, book_jtd_cost / book_fcst_cost))
AS BOOK_PCT_CMPL,
Iif(fsjob.stat_cd <> 'A', Round(jtd_gross_bill + accrued_billing, 2),
Iif(fsjob.job_type = 2,
Iif(( book_jtd_cost + Nz(fsjob.fcst_job_profit) ) < (
book_contract_amt * book_pct_cmpl ),
Nz(fsjob.fcst_job_profit) + book_jtd_cost, Round(
book_pct_cmpl * book_contract_amt, 2)),
Iif(Nz(fsjob.fcst_job_profit) < 0, Nz(fsjob.fcst_job_profit) + book_jtd_cost, Iif(book_pct_cmpl < 0.195, book_jtd_cost,
Round(
book_pct_cmpl * book_contract_amt, 2)))))
AS
BOOK_JTD_EARNED_REV,
( book_jtd_earned_rev - book_jtd_cost )
AS BOOK_JTD_PROFIT,
Iif(fsjob.stat_cd = 'C', book_jtd_profit, Nz(fsjob.fcst_job_profit))
AS
BOOK_FCST_PROFIT,
( book_contract_amt - book_fcst_profit - book_jtd_cost )
AS BOOK_COST_TO_CMPL,
( Nz(fsjob.prior_bk_rev) - Nz(fsjob.prior_bk_cost) )
AS BOOK_PRIOR_PROFIT,
Round(book_jtd_cost - Nz(fsjob.prior_bk_cost), 2)
AS BOOK_YTD_COST,
Round(book_jtd_earned_rev - Nz(fsjob.prior_bk_rev), 2)
AS BOOK_YTD_EARNED_REV,
( book_ytd_earned_rev - book_ytd_cost )
AS BOOK_YTD_PROFIT,
Iif(fsjob.stat_cd = 'C', 0, Nz(fsjob.fcst_ye_labor) - jtd_labor_cost)
AS
LABOR_COST_TO_CMPL,
Round(jtd_gross_bill + accrued_billing - book_jtd_earned_rev, 2)
AS
BOOK_EXCESS_BILLING,
Round(Iif(( fsjob.sdp_cd = 'SDP'
AND fsjob.stat_cd = 'I' )
OR ( fsjob.sdp_cd = 'SDP'
AND Nz(jtd_gross_bill) > 0
AND fsjob.stat_cd = 'A'
AND
Nz(jtd_sub_cost) > 0 ), variable.sdp_pct * Nz(fsjob.fcst_sc_cost), 0), 2)
AS
SDP_REV,
Round(Iif(fsjob.sdp_cd IS NOT NULL
AND
fsjob.stat_cd <> 'C',
Iif(Nz(fsjob.fcst_sc_cost) > Nz(jtd_sub_cost),
Nz(fsjob.fcst_sc_cost) * variable.sdp_pct, Nz(jtd_sub_cost) * variable.sdp_pct), 0), 2)
AS FCST_SDP_REV,
Round(Iif(fsjob.sdp_cd IS NOT NULL
AND
fsjob.stat_cd <> 'C',
Nz(fsjob.sc_cost) / variable.ytd_sdp_sub_cost * variable.ytd_sdp_exp, 0), 2)
AS SDP_EXP,
( Nz(sdp.prior_cost) + Nz(sdp.curr_cost)
+ Nz(sdp.curr_ap) - Nz(sdp.prior_ap) + sdp_exp )
AS JTD_SDP_EXP,
Iif(fsjob.sdp_cd <> 'SDP'
OR fsjob.stat_cd = 'C', 0, Round(Nz(fsjob.fcst_sc_cost) - jtd_sub_cost, 2))
AS SUB_COST_TO_CMPL,
fcst_sdp_rev - jtd_sdp_exp - fcst_sdp_addl_reserve_amt
AS FCST_SDP_PROFIT,
sdp_rev - jtd_sdp_exp
AS SDP_PROFIT,
Iif(book_pct_cmpl < 0.195, Round(( fcst_sdp_rev - jtd_sdp_exp ) * 0.5, 2), 0)
AS
FCST_SDP_ADDL_RESERVE_AMT,
Iif(Nz(fsjob.fcst_job_profit) < 0, fcst_sdp_profit - Nz(fsjob.prior_sdp_credit), Iif(book_pct_cmpl < 0.195, 0,
Round(
book_pct_cmpl * fcst_sdp_profit - Nz(fsjob.prior_sdp_credit), 2)))
AS
YTD_SDP_CREDIT,
Iif(fsjob.stat_cd = 'C', fcst_sdp_profit,
Iif(Nz(fsjob.fcst_job_profit) < 0, fcst_sdp_profit - Nz(fsjob.prior_sdp_credit),
Iif(Nz(fsjob.fcst_ye_pct_cmpl) < 0.195, 0,
Round(Nz(fsjob.fcst_ye_pct_cmpl) * fcst_sdp_profit - Nz(fsjob.prior_sdp_credit), 2)))) AS FCST_SDP_CREDIT,
sdp_profit - ytd_sdp_credit - Nz(fsjob.prior_sdp_credit)
AS YTD_SDP_RESERVE_AMT,
ytd_sdp_credit + Nz(fsjob.prior_sdp_credit)
AS JTD_SDP_CREDIT,
Round(Nz(eq_aed.eq_aed_chrg) / variable.ytd_eq_rev * variable.ytd_eq_profit, 2)
AS YTD_EQ_CREDIT,
ytd_eq_credit + Nz(fsjob.prior_eq_credit)
AS JTD_EQ_CREDIT,
Round(fsjob.ti_pct * Nz(fsjob.fcst_labor_cost), 2)
AS FCST_TI_COST,
audit_ytd_ti_cost + Nz(fsjob.prior_adt_ti)
AS AUDIT_JTD_TI_COST,
Switch(fsjob.ti_pct = 0.1, Nz(fsjob.ti_cost), true,
Round((jtd_labor_cost-Nz(fsjob.prior_labor_cost))*variable.actual_ti_pct, 2)
+ Nz(fsjob.wc_cost, 0))
AS AUDIT_YTD_TI_COST
FROM ((fsjob
LEFT JOIN variable
ON fsjob.var_ctrl_num = variable.var_ctrl_num)
LEFT JOIN eq_aed
ON fsjob.job_id = eq_aed.job_id)
LEFT JOIN sdp
ON fsjob.job_id = sdp.job_id;
The deepest nested IIF in all of these is only 3 deep and the most complex Switch statement only has 4 options. And the fields used in these statements are not overly complex, either. I've been fighting to simplify this for about a week and don't believe I can make it any more concise.
Thanks in advance.
So, I have the current script below, but I need to create this as a view and I know you can't use variable within it. I understand there is the option of creating a stored procedure, but I'm not quite sure how to go about.
Create View vwPUs__cwa as (
Declare #salt varchar (25);
DECLARE #Seed int;
DECLARE #LCV tinyint;
DECLARE #CTime DATETIME;
SET #CTime = GETDATE();
SET #Seed = (DATEPART(hh, #Ctime) * 10000000) + (DATEPART(n, #CTime) * 100000)
+ (DATEPART(s, #CTime) * 1000) + DATEPART(ms, #CTime);
SET #LCV = 1;
SET #Salt = CHAR(ROUND((RAND(#Seed) * 94.0) + 32, 3));
WHILE (#LCV < 25)
BEGIN
SET #Salt = #Salt + CHAR(ROUND((RAND() * 94.0) + 32, 3));
SET #LCV = #LCV + 1;
END;
SELECT dc.id,
sys.Fn_varbintohexsubstring(0, Hashbytes('SHA2_512', #salt + dc.decrypt),
1, 0)
AS SaltyHashbrowns,
dc.firstname,
dc.lastname,
dc.statusname,
dc.processingunit,
dc.processingunitnumber
FROM vwdecrypt_cwa dc
WHERE dc.processingunitnumber IN ( 0201301, 0201302, 0201303, 0201308,
0201309, 0201311, 0201312 )
;
The Prcoedure you need to create will be along the lines of
create procedure PUs__cwa
as
set nocount on
declare #salt varchar (25), #Seed int, #LCV tinyint=1, #CTime datetime=GetDate()
set #Seed = (DatePart(hh, #CTime) * 10000000) + (DatePart(n, #CTime) * 100000)
+ (DatePart(s, #CTime) * 1000) + DatePart(ms, #CTime);
set #salt = Char(Round((Rand(#Seed) * 94.0) + 32, 3));
while (#LCV < 25)
begin
set #salt = #salt + Char(Round((Rand() * 94.0) + 32, 3));
set #LCV += 1;
end;
select dc.id,
sys.fn_varbintohexsubstring(0, HashBytes('SHA2_512', #salt + dc.decrypt), 1, 0) as SaltyHashbrowns,
dc.firstname,
dc.lastname,
dc.statusname,
dc.processingunit,
dc.processingunitnumber
from vwdecrypt_cwa dc
where dc.processingunitnumber in ( 0201301, 0201302, 0201303, 0201308, 0201309, 0201311, 0201312 )
And you run it in tsql with exec PUs__cwa
An inline Table-Valued Function would work here. It is effectively treated by the compiler as a parameterized view.
You cannot place RAND() in a UDF, so we must do this in a stored procedure and pass it through:
CREATE OR ALTER FUNCTION vwPUs__cwa (#salt varchar (25))
RETURNS TABLE
AS RETURN
(
SELECT dc.id,
sys.Fn_varbintohexsubstring(0, Hashbytes('SHA2_512', #salt + dc.decrypt),
1, 0)
AS SaltyHashbrowns,
dc.firstname,
dc.lastname,
dc.statusname,
dc.processingunit,
dc.processingunitnumber
FROM vwdecrypt_cwa dc
WHERE dc.processingunitnumber IN ( 0201301, 0201302, 0201303, 0201308,
0201309, 0201311, 0201312 )
);
GO
CREATE OR ALTER PROCEDURE PUs__cwa
AS
SET NOCOUNT, XACT_ABORT ON;
DECLARE #salt varchar(25);
DECLARE #Seed int = (DATEPART(hh, #Ctime) * 10000000) + (DATEPART(n, #CTime) * 100000) + (DATEPART(s, #CTime) * 1000) + DATEPART(ms, #CTime);
DECLARE #LCV tinyint = 1;
DECLARE #CTime DATETIME = GETDATE();
WHILE (#LCV < 25)
BEGIN
SET #LCV = #LCV + 1;
SET #Salt = CONCAT(#Salt, CHAR(ROUND((RAND() * 94.0) + 32, 3)));
END;
SELECT *
FROM vwPUs__cwa (#salt);
GO
You could also run the salt code in a client application, and pass it through as a parameter to an ad-hoc batch:
SELECT *
FROM vwPUs__cwa (#salt);
I am having a problem when trying to summarise my aditive predictor:
mu[j] <- b0 + weights1[1] * A[j] + weights1[2] * A[j+1] + weights1[3] * A[j+2] + weights1[4] * A[j+3] +
weights1[5] * A[j+4] + weights1[6] * A[j+5] + weights1[7] * A[j+6] + weights1[8] * A[j+7] +
weights1[9] * A[j+8] + weights1[10] * A[j+9] + weights1[11] * A[j+10] + weights1[12] * A[j+11] +
weights2[1] * B[j] + weights2[2] * B[j+1] + weights2[3] * B[j+2] + weights2[4] * B[j+3] +
weights2[5] * B[j+4] + weights2[6] * B[j+5] + weights2[7] * B[j+6] + weights2[8] * B[j+7] +
weights2[9] * B[j+8] + weights2[10] * B[j+9] + weights2[11] * B[j+10] + weights2[12] * B[j+11]
by using inprod(). This is what I thought should be the equivalent:
mu[j] <- b0 + inprod(weights1[],A[j:(j+11)]) + inprod(weights2[],B[j:(j+11)])
While the model compiles and seems to work, it stays updating forever. Its been running for hours and it does not end while the first approach ends in few minutes.
These are the priors, just in case:
weights1[1] ~ dnorm(0,1.0E-6)
weights2[1] ~ dnorm(0,1.0E-6)
for(t in 2:12) {
weights1[t]~dnorm(weights1[t-1],tauweight1)}
for(t in 2:12) {
weights2[t]~dnorm(weights2[t-1],tauweight2)}
b0 ~ dnorm(0,.001)
tau ~ dgamma(0.001, 0.001)
sigma <- 1/sqrt(tau)
tauweight1~dgamma(1.0E-3,1.0E-3)
tauweight2~dgamma(1.0E-3,1.0E-3)
I am calling OpenBUGS from R using R2OpenBUGS just in case.
Thanks very much for your time!
I'm trying to rewrite the following code to use a variable instead of magic numbers:
SELECT tokenId,
IIF(LEN(ref) < 4, ref, REPLICATE(CONVERT(NVARCHAR(20),'*'), LEN(ref)-4) + SUBSTRING(ref, (LEN(ref)-3), LEN(ref))) as refMasked
FROM tokenBase
WHERE (refMasked is null or refMasked = '') AND ref is not null AND ref <> ''
I tried doing it like this:
DECLARE #NumberOfCharsAtEndOfStringToNotMask INTEGER
SET #NumberOfCharsAtEndOfStringToNotMask = 4 --Why do I need to set this to 2 for it to work?
SELECT tokenId,
IIF(LEN(ref) < #NumberOfCharsAtEndOfStringToNotMask, ref, REPLICATE(CONVERT(NVARCHAR(20),'*'), LEN(ref)-#NumberOfCharsAtEndOfStringToNotMask) + SUBSTRING(ref, (LEN(ref)-#NumberOfCharsAtEndOfStringToNotMask-1), LEN(ref))) as refMasked
FROM tokenBase
WHERE (refMasked is null or refMasked = '') AND ref is not null AND ref <> ''
However it doesn't work if I use #NumberOfCharsAtEndOfStringToNotMask = 4, I need to use 2 instead. Why is this?
If I use 4 then the last 6 chars of the string are left unmasked, however I need the last 4 chars to be unmasked. Using a value of 2 fixes this but I have no idea why.
EDIT
Amit has suggested I use the following code which works:
IIF(LEN(ref) < #NumberOfCharsAtEndOfStringToNotMask, ref,REPLICATE(CONVERT(NVARCHAR(20),'*'), LEN(ref)-#NumberOfCharsAtEndOfStringToNotMask) + SUBSTRING(ref, (LEN(ref)-#NumberOfCharsAtEndOfStringToNotMask+1),#NumberOfCharsAtEndOfStringToNotMask)) as refMasked
Why does this work? Why can't I just replace the use of 4 with a variable storing the value of 4?
Try this Dave:
DECLARE #C INTEGER = 4;
SELECT bpayreference
, LEN(bpayreference) As LengthOfString
, LEN(bpayreference) - #C AS MinusC
, SUBSTRING(bpayreference , (LEN(bpayreference) - #C) + 1 , (LEN(bpayreference) ) - (LEN(bpayreference) - #C))
, CASE
WHEN (LEN(bpayreference) < #C) THEN REPLICATE('*' , LEN(bpayreference) - #C)
ELSE
REPLICATE('*' , LEN(bpayreference) - #C )
+ SUBSTRING(bpayreference , (LEN(bpayreference) - #C) + 1 , (LEN(bpayreference) ) - (LEN(bpayreference) - #C))
END
FROM tokenbase
Replace your iif block with this one and see how you go
IIF(LEN(ref) < #NumberOfCharsAtEndOfStringToNotMask, ref,REPLICATE(CONVERT(NVARCHAR(20),'*'), LEN(ref)-#NumberOfCharsAtEndOfStringToNotMask) + SUBSTRING(ref, (LEN(ref)-#NumberOfCharsAtEndOfStringToNotMask+1),#NumberOfCharsAtEndOfStringToNotMask)) as refMasked