I am working on an MS Access to SQL Server Migration project and am currently in the process of converting a complex query into T-SQL from MS Access.
Now I'm quite familiar with how Nz works in Access and how a 0 or empty string " " is returned if the valueifnull argument is not provided.
Source: https://support.office.com/en-gb/article/nz-function-8ef85549-cc9c-438b-860a-7fd9f4c69b6c
The exception to this rule is if the Nz function is used within a query expression, in which case, the returned value in the event of a null in the Variant, is an empty string.
Now, moving onto my actual problem, I am working on converting this Nz-filled query expression into T-SQL using ISNULL in T-SQL.
ISNULL requires 2 arguments. Both the Expression and the Value. The latter being an optional argument in Access' Nz, has made it a bit difficult for me to translate the expression. The Value argument also needs to match the original data type of the Variant (in SQL Server), this means that I can not just simply add an empty string " " as the second argument as Nz in Access does by default.
Take a snippet of the complex query I use in Access compared to what I've written in T-SQL:
Access
TotalWIP: IIf([PercentageDoneTotal]<0,0,IIf(nz([TotalPurchasesReceived])+
(IIf([PercentageDoneTotal]>0,nz([TotalStockAllocated]),0))+IIf((([Accepted
Price]*[OutstandingBalance]*0.9)-nz([TotalPurchasesReceived])-
(IIf([PercentageDoneTotal]>0,nz([TotalStockAllocated]),0)))>0,((([Accepted
Price]*[OutstandingBalance]*0.9)-nz([TotalPurchasesReceived])-
(IIf([PercentageDoneTotal]>0,nz([TotalStockAllocated]),0)))*
[PercentageDoneTotal]),0)>([Accepted Price]*[OutstandingBalance]*0.9),
([Accepted Price]*[OutstandingBalance]*0.9),nz([TotalPurchasesReceived])+
(IIf([PercentageDoneTotal]>0,nz([TotalStockAllocated]),0))+IIf((([Accepted
Price]*[OutstandingBalance]*0.9)-nz([TotalPurchasesReceived])-
(IIf([PercentageDoneTotal]>0,nz([TotalStockAllocated]),0)))>0,((([Accepted
Price]*[OutstandingBalance]*0.9)-nz([TotalPurchasesReceived])-
(IIf([PercentageDoneTotal]>0,nz([TotalStockAllocated]),0)))*
[PercentageDoneTotal]),0)))
T-SQL
IIf([PercentageDoneTotal]<0,0,
IIf(ISNULL([TotalPurchasesReceived],NULL)+
(IIf([PercentageDoneTotal]>0,ISNULL([TotalStockAllocated],NULL),0))+
IIf((([Accepted Price]*[OutstandingBalance]*0.9)-
ISNULL([TotalPurchasesReceived],NULL)
-(IIf([PercentageDoneTotal]>0,ISNULL([TotalStockAllocated],NULL),0)))>0,
((([Accepted Price]*[OutstandingBalance]*0.9)-
ISNULL([TotalPurchasesReceived],NULL)-
(IIf([PercentageDoneTotal]>0,ISNULL([TotalStockAllocated],NULL),0)))*
[PercentageDoneTotal]),0)>([Accepted Price]*[OutstandingBalance]*0.9),
([Accepted Price]*
[OutstandingBalance]*0.9),ISNULL([TotalPurchasesReceived],NULL)+
(IIf([PercentageDoneTotal]>0,ISNULL([TotalStockAllocated],NULL),0))+
IIf((([Accepted Price]*[OutstandingBalance]*0.9)-
ISNULL([TotalPurchasesReceived],NULL)-
(IIf([PercentageDoneTotal]>0,ISNULL([TotalStockAllocated],NULL),0)))>0,
((([Accepted Price]*[OutstandingBalance]*0.9)-
ISNULL([TotalPurchasesReceived],NULL)-
(IIf([PercentageDoneTotal]>0,ISNULL([TotalStockAllocated],NULL),0)))*
[PercentageDoneTotal]),0))
) AS TotalWIP
Note the above NULL in the T-SQL example. This NULL is not suitable as it is messing up my calculations, I essentially need to mimic Nz without a second argument in T-SQL.
Edit:
Without putting the entire query into this question, Here is an expected result for Job Number: 294784 in both MS Access and SQL Server:
Access Results:
SQL Results:
Edit 2: have added the edited to add entire code.
As #Salman A noted, this is a great reason not to use variant. But having said that, I assume that you are looking for a numeric value, so why not use:
IIF([PercentageDoneTotal]<0,0, IIF(ISNULL([TotalPurchasesReceived],0)+
(IIF([PercentageDoneTotal]>0,ISNULL([TotalStockAllocate],0),0))
Related
I have a column called "Bakery Activity" whose values are all JSONs that look like this:
{"flavors": [
{"d4js95-1cc5-4asn-asb48-1a781aa83": "chocolate"},
{"dc45n-jnsa9i-83ysg-81d4d7fae": "peanutButter"}],
"degreesToCook": 375,
"ingredients": {
"d4js95-1cc5-4asn-asb48-1a781aa83": [
"1nemw49-b9s88e-4750-bty0-bei8smr1eb",
"98h9nd8-3mo3-baef-2fe682n48d29"]
},
"numOfPiesBaked": 1,
"numberOfSlicesCreated": 6
}
I'm trying to extract the number of pies baked with a regex function in Tableau. Specifically, this one:
REGEXP_EXTRACT([Bakery Activity], '"numOfPiesBaked":"?([^\n,}]*)')
However, when I try to throw this calculated field into my text table, I get an error saying:
ERROR: function regexp_matches(jsonb, unknown) does not exist;
Error while executing the query
Worth noting is that my data source is PostgreSQL, which Tableau regex functions support; not all of my entries have numOfPiesBaked in them; when I run this in a simulator I get the correct extraction (actually, I get "numOfPiesBaked": 1" but removing the field name is a problem for another time).
What might be causing this error?
In short: Wrong data type, wrong function, wrong approach.
REGEXP_EXTRACT is obviously an abstraction layer of your client (Tableau), which is translated to regexp_matches() for Postgres. But that function expects text input. Since there is no assignment cast for jsonb -> text (for good reasons) you have to add an explicit cast to make it work, like:
SELECT regexp_matches("Bakery Activity"::text, '"numOfPiesBaked":"?([^\n,}]*)')
(The second argument can be an untyped string literal, Postgres function type resolution can defer the suitable data type text.)
Modern versions of Postgres also have regexp_match() returning a single row (unlike regexp_matches), which would seem like the better translation.
But regular expressions are the wrong approach to begin with.
Use the simple json/jsonb operator ->>:
SELECT "Bakery Activity"->>'numOfPiesBaked';
Returns '1' in your example.
If you know the value to be a valid integer, you can cast it right away:
SELECT ("Bakery Activity"->>'numOfPiesBaked')::int;
I found an easier way to handle JSONB data in Tableau.
Firstly, make a calculated field from the JSONB field and convert the field to a string by using str([FIELD_name]) command.
Then, on the calculated field, make another calculated field and use function:
REGEXP_EXTRACT([String_Field_Name], '"Key_to_be_extracted":"?([^\n,}]*)')
The required key-value pair will form the second caluculated field.
IC=IC
ACC=ACC
v_statement='ACC = '1052502',0.035,IC = 'IC130',0.0675'
v_decode_out=DECODE(TRUE,v_statement,0)
i am getting error
is the above expression correct.Is there anyway we can achieve this
There are two problems in your query
First, the v_statement variable you have written won't be validated. If you
really want to write a string in this format, then use pipes to append as
'ACC='||1052502||','||0.035||'IC='||'IC130'||','||'0.0675'
Note that you cannot loop quotes.
Second, the reason your decode statement wont work is because of the data type mismatch. True is a boolean value and v_statement is a string. Any variable expansion would happen during run time but not before that. So, informatica does not allow you this kind of decode statement, unless you are comparing some kind of string input/variable with another string or any other data type for that matter
Also, decide on your case
When it is If ACC else IC to be evaluated (this seems to be your case)
v_decode_out=DECODE(ACC,'1052502',0.035,DECODE(IC,'IC130',0.0675))
When it is both ACC and IC together
v_decode_out=DECODE(TRUE,ACC='1052502' and/or IC='IC130',0.035,0.0675)
These are fundamental concepts. It's advisable that you try out everything available on internet before you post a question here, because someone could easily down rate you if they feel that you have not put any effort at all to find an answer yourself.
Cheers!
the v_statement variable you have written won't be validated. If you really want to write a string in this format, then use pipes to append.
I have two datasets in my report and data is being displayed through a table. When I give expression like below:
=Format(Fields!InvDt.Value, "dsRepSalesReport_tblPrintSalesReport","dd/MMMyyyy")
It says there is Syntax error. If I remove dsRepSalesReport_tblPrintSalesReport part, there is no error.
1) Please advise how to wite the expression in format with aggregate expression.
2) If I write expression without dsRepSalesReport_tblPrintSalesReport part, my table repeats data and shows for all invoice. But when I add aggregate part, dsRepSalesReport_tblPrintSalesReport
Table just shows one value several times.
Please advise how to handel with these two issues.
Thanks
The method signature for Format is:
Public Shared Function Format(
ByVal Expression As Object,
Optional ByVal Style As String = ""
) As String
So that means you can't just specify the field and the Scope as in your first example; the first of the two arguments must return one value only.
In your example, you could use something like:
=Format(First(Fields!InvDt.Value, "dsRepSalesReport_tblPrintSalesReport"), "dd/MMMyyyy")
Which will format the first value in the specified Scope.
Another option would be to just set the value as required in the report then use the Format property:
It's difficult to answer your second question without knowing what your data/required results are... If you update the question with some simplified sample data to illustrate the actual issue you're facing that would be helpful.
I have SQL function, it is not written by me.
I am having hard time understanding, what does following condition mean?
specifically :key and ||cLF||'.
WHERE ' WHERE 1=1 '
||cLF||' AND f.key = :key '
||cLF||' AND i.flag = 0'
||cLF||' AND r.flag = 0'
First, the || operator is a string concatenation operator. So it looks like the code is building a WHERE clause using conditions specified by cLF. Though I'm not entirely sure why they're tacking on cLF three times there.
The :key syntax refers to a parameter in a parameterized query. Its value will be passed in when the SQL statement you're building is actually run.
The query you have pasted is a part of a dynamically constructed SQL statement.
Semicolon here points to a bind-place holder, meaning that the actual value for ":key" is passed through an argument and not hard coded.
Read examples on EXECUTE IMMEDIATE.
Following my question in https://stackoverflow.com/questions/7387418/where-clause-using-date-taken-from-string-variable-sent-out-incorrect-return-in-s, this is the simplified version of the question:
The query used for the OLE DB Source is this, with a string type variable inside:
select
*
from
A
where
A.A_IN_DATETIME < CONVERT(DATETIME,?,105) and
(A.A_OUT_DATETIME is NULL or A.A_OUT_DATETIME >= CONVERT(DATETIME,?,105))
The query above works inside a Foreach Variable Enumerator, with the variable used is an array of string variable consisting of this: 13-09-2011,12-09-2011,11-09-2011,10-09-2011,09-09-2011,08-09-2011,07-09-2011,06-09-2011,05-09-2011,04-09-2011,03-09-2011,02-09-2011,01-09-2011
The condition for the problem is this: For example, there is a record in A with A_IN_DATETIME = 2011-09-12 (YYYY-MM-DD format) and A_OUT_DATETIME = NULL.
The correct result for the query above that it should have been only returning values for 13-09-2011 and the rest return 0 records, but in the execution, there was a result for 12-09-2011 to 10-09-2011 also. I don't know if the SSIS somehow mistaken the 12-09-2011, 11-09-2011, 10-09-2011 to 09-12-2011,09-11-2011,09-10-2011 (FYI, I've checked the parsing result and also the loop enumerator by printing it out in a message box generated from the script task, and it is still in its correct form).
Is there any solution for this problem?
Run Sql Profiler and see what query comes through to SQL Server. This will allow you to re-run the exact query in SSMS and see the results right there.
I don't believe conversion to DATETIME accepts a format, i.e. 105.Try this instead:
CONVERT(DATETIME, '9/13/2011 15:37:00')
Result is DATETIME - 2011-09-13 15:37:00.000