XPATH expression with negating condition in SAP PI XSLT Mapping - xpath

I have to maintain conditions in Interface Determination of ICO in SAP PI. I have several invoice types like L1, S1, G1, F1, etc. I have two separate mappings as per requirement.
When the Invoice type is L1, S1 or G1, and LAND1 = IND, PARW= W and QUALF=015, I want to pick 1st mapping and for remaining invoice types I want to pick 2nd mapping.
The XPath expressions in the Condition Editor for the two mappings are:
1)
(/ZEINV_INVOIC02/IDOC/E1EDKA1[PARVW = 'W' and LAND1 = 'IND']) EX AND
(/ZEINV_INVOIC02/IDOC/E1EDK14[QUALF = 015 and ORGID = 'L1']) EX OR
(/ZEINV_INVOIC02/IDOC/E1EDKA1[PARVW = 'W' and LAND1 = 'IND']) EX AND
(/ZEINV_INVOIC02/IDOC/E1EDK14[QUALF = 015 and ORGID = 'G1']) EX OR
(/ZEINV_INVOIC02/IDOC/E1EDKA1[PARVW = 'W' and LAND1 = 'IND']) EX AND
(/ZEINV_INVOIC02/IDOC/E1EDK14[QUALF = 015 and ORGID = 'S1']) EX
2) (I have an issue with the second line about ORGID expression)
(/ZEINV_INVOIC02/IDOC/E1EDKA1[PARVW = 'W' and LAND1 = 'IND']) EX AND
(/ZEINV_INVOIC02/IDOC/E1EDK14[QUALF = 015 and ( ORGID ≠ 'L1' or ORGID ≠ 'G1' or ORGID ≠ 'S1' )]) EX
The issue is that when the ICO is run, it is picking both mappings, satisfying both conditions with these values:
ORGID = 'L1'
QALF = 015
PARW = 'W'
LAND1 = 'IND'
What is the XPath expression for the second condition when we have ORGID values other than L1, G1 and S1?

Unfortunately, the expression ORGID ≠ 'L1' or ORGID ≠ 'G1' or ORGID ≠ 'S1' is a tautology, i.e. it's true if ORGID is 'L1' and true if ORGID is not L1, so the whole expression is always true whatever the value of ORGID is.
What you want is this:
not( ORGID = 'L1' or ORGID = 'G1' or ORGID = 'S1' )
Note that you may also use the equivalent expression without not, by using the De Morgan's law, here you have to switch and/or and negate the conditions:
ORGID != 'L1' and ORGID != 'G1' and ORGID != 'S1'
NB: does ≠ really work? Shouldn't you use !=?

Related

Oracle co related query?

How does co-related query works? Does inner query iterate according to outer query rows? Suppose I have student table with only 1 ID columns with vlaues 1, 2, 3. Can any body gives pictorial example?
select count(*)
from student s where s.sid < any (select s1.id from student s1 where s1.id < s.id);
The correlated subquery is (theoretically - without considering possible optimization) performed once for each row of the main table (s).
For the s.ID = 1 the subquery returns no row (s1.ID < 1 return nothing)
for the s.ID = 2 it returns 1 and (predicate s1.id < 2)
for the s.ID = 3 it returns 1,2
Therefore the first row (s.ID=1) is not selected (the subquery return no row),
for the second row (s.ID =2) the predicate is s.id < any ( 1 ) which is rewritten to s.id < 1 see rules for ANY
and the row is not selected as 2 < 1 is FALSE
for the third row (s.ID = 3) the predicate is s.id < any ( 1,2 ) which is rewritten to s.id < 1 OR s.id < 2 which is FLASE as well.
So the query
create table student as
select rownum id from dual connect by level <= 3;
select *
from student s where s.id < any (select s1.id from student s1 where s1.id < s.id);
return empty result (no rows).

how to filter out null value then compare in oracle

I tried this, and it works,
SELECT name
FROM
(SELECT name,LENGTH FROM river WHERE LENGTH IS NOT NULL
)
WHERE LENGTH >= ALL
(SELECT LENGTH FROM
(SELECT name,LENGTH FROM river WHERE LENGTH IS NOT NULL
)
)
but my final code would be like this:
SELECT a.name,
a.length
FROM
(SELECT name,LENGTH FROM river WHERE LENGTH IS NOT NULL
) a,
geo_river b,
encompasses c
WHERE a.length >= ALL
(SELECT a2.LENGTH
FROM
(SELECT name,LENGTH FROM river WHERE LENGTH IS NOT NULL
) a2
)
AND a.name = b.river
AND b.country = c.country
AND c.continent = 'America'
this is really complicated.
Is there an easy way to let
(SELECT name,LENGTH FROM river WHERE LENGTH IS NOT NULL)
be river, so I don't need to use this
(SELECT name,LENGTH FROM river WHERE LENGTH IS NOT NULL)
two times.
If you want to simplify your code writing, you can use WITH:
with viewA as (SELECT name,LENGTH FROM river WHERE LENGTH IS NOT NULL )
SELECT a.name,
a.length
FROM
viewA a,
geo_river b,
encompasses c
WHERE a.length >= ALL
(SELECT a2.LENGTH
FROM
viewA a2
)
AND a.name = b.river
AND b.country = c.country
AND c.continent = 'America'
Using a single table scan:
SELECT name,
length
FROM (
SELECT name,
length,
RANK() OVER ( ORDER BY length DESC ) AS rnk
FROM river
)
WHERE rnk = 1;
So your code would then be:
SELECT a.name,
a.length
FROM (
SELECT name,
length
FROM (
SELECT name,
length,
RANK() OVER ( ORDER BY length DESC ) AS rnk
FROM river
)
WHERE rnk = 1
) a
INNER JOIN
geo_river b
ON ( a.name = b.river )
INNER JOIN
encompasses c
ON ( b.country = c.country )
WHERE c.continent = 'America';
I don't think you need to filter out null lengths as they won't show up if you subset on length (i.e. when comparing NULL values without using the NVL function the comparison will always evaluate to false and not show the row). So something simple such as:
Select a.name, a.length
from river a, geo_river b, encompasses c
WHERE a.length > 0
AND a.name = b.river
AND b.country = c.country
AND c.continent = 'America'
;
Will do the trick

Compare two Rows in a worksheet and test for Unique values for each and Output in an Column

I have a worksheet with two columns with different Values, Patient ID (ID#) and Institute.
I want to find the Unique values between the two columns and output as 1 (is unique) and 0 (not unique) in an different column corresponding to each cell.
I need to use an Array as I have 10,000 records to test in each column.
Test Conditions:
Case 1 : PatientID in value (A1 = "HC1") goes to Institute value (B2 = "HG"). This is an unique value, as PatientID and Institute only appear once. Hence Output in value (C1 = "1").
Case 2 : PatientID value (A2 = "HC1") goes to Institute value (B2 = "HG"). This is an not unique; as the same patient goes to the same institute again. Hence Output in value (C2 = "0").
Case 3 : PatientID value (A3 = "HC1") goes to Institute value (B3 = "RH"). This is unique; as the same patient goes to an different Institute. Hence Output in value (C3 = "1").
Case 4 : PatientID value (A4 = "HC2") goes to institute value (B4 = "RH"). This is unique; as different patient goes to an different institute. Hence the value of Output should be value (C4 = "1").
I need the VB code to do the same.
Currently i use this Excel 2010 Formulae,
=IF(SUMPRODUCT(($C$2:$C1442=C3)*($A$2:$A1442=A3))>1,0,1)
where,
Column C is Institute and Column A is PatientID.
This takes insane amount of time to compute. Please HELP.
Thank you
You can use a helper column to combine the two cells together, then count if those cells are unique.
Results
if you want you can hide column C
If you want to use macro for the same, you can do it as follow:
Sub TEST()
Set ExcelAppl = CreateObject("Excel.Application")
Set wb = ActiveWorkbook
Set ActiveRange = wb.Worksheets(1).UsedRange
RowCont = ActiveRange.Rows.Count
Dim dataArr() As Variant
ReDim dataArr(RowCont, 1)
For i = 0 To RowCont - 1
InputText = Cells(i + 1, 1).Value & Cells(i + 1, 2).Value
If CheckUnique(dataArr, InputText) = True Then
Cells(i + 1, 3).Value = 0
Else
Cells(i + 1, 3).Value = 1
dataArr(i, 0) = InputText
dataArr(i, 1) = i + 1 'store row number
End If
Next
End Sub
Function CheckUnique(dataArr, InputText)
Dim lb As Long, ub As Long, i As Long, result As Boolean
lb = LBound(dataArr)
ub = UBound(dataArr)
result = False
For i = lb To ub
If dataArr(i, 0) = InputText Then
result = True
Cells(i + 1, 3).Value = 0
Exit For
End If
Next i
CheckUnique = result
End Function
Output will be:

Duplicating rows in an oracle query

I am to create a query which will be used for printing labels in our project and find it difficult since the count of the number of labels is based on a string. I have made a query that looks like this:
SELECT
wipdatavalue
, containername
, l
, q as qtybox
, d
, qtyperbox AS q
, productname
, dt
, dsn
, CASE
WHEN instr(wipdatavalue, '-') = 0
THEN
to_number(wipdatavalue)
ELSE
to_number(substr(wipdatavalue, 1, instr(wipdatavalue, '-') - 1))
END AS una
, CASE
WHEN instr(wipdatavalue, '-') = 0
THEN
to_number(wipdatavalue)
ELSE
to_number(substr(wipdatavalue, instr(wipdatavalue, '-') + 1))
END AS dulo
, ROW_NUMBER() OVER (ORDER BY containername) AS n
, count(*) over() m
FROM trprinting_ls
WHERE containername = 'TRALTESTU0A'
GROUP BY wipdatavalue, containername, l, q, d, qtyperbox, productname, dt, dsn
ORDER BY wipdatavalue
The query above will result to below:
But actually, I have to display the first Item (Wipdatavalue 1-4) not only once but four times to look something like this:
I have tried another query that runs fine but when I try to load it in our project, it does not print the label. We found out that it is because of the WITH statement and we don't know why. The query is:
WITH DATA (WIPDATAVALUE, CONTAINERNAME, L, Q, D, QTYBOX, PRODUCTNAME, DT, una, dulo, m1, n)
AS (SELECT WIPDATAVALUE, CONTAINERNAME, L, Q, D, QTYBOX, PRODUCTNAME, DT, una, dulo,(dulo - una) + 1 AS m1,una n
FROM (SELECT WIPDATAVALUE, CONTAINERNAME, L, Q, D, QTYPERBOX AS QTYBOX, PRODUCTNAME, DT,
CASE
WHEN instr(wipdatavalue, '-') = 0
THEN
to_number(wipdatavalue)
ELSE
to_number(substr(wipdatavalue, 1, instr(wipdatavalue, '-') - 1))
END AS una,
CASE
WHEN instr(wipdatavalue, '-') = 0
THEN
to_number(wipdatavalue)
ELSE
to_number(substr(wipdatavalue, instr(wipdatavalue, '-') + 1))
END AS dulo
FROM trprinting_ls
WHERE containername = 'TRALTESTU0A'
)
UNION ALL
SELECT WIPDATAVALUE, CONTAINERNAME, L, Q, D, QTYBOX, PRODUCTNAME, DT, una, dulo, m1, n + 1
FROM DATA
WHERE n + 1 <= dulo)
SELECT WIPDATAVALUE, CONTAINERNAME, L, Q, D, QTYBOX, PRODUCTNAME, DT, una, dulo, n,
count(*) OVER () m
FROM DATA
ORDER BY n, wipdatavalue
Thanks guys for helping out.
Try this
select *
from your_data
start with instr(Wipdatavalue, '1') > 0
connect by level between regexp_substr(Wipdatavalue, '^\d+')
and regexp_substr(Wipdatavalue, '\d+$')
It's a simplified example
The regexp_substr can be replaced with substr and instr if you like (may also be faster)
Here is a sqlfiddle demo
Try this Query
select column_name, count(column_name)
from table
group by column_name
having count (column_name) > 1;

Multiple Distincts with Linq

given the following information I have in a database table:
Col 1, Col2, Col3
1 , x , G
1 , y , H
2 , z , J
2 , a , K
2 , a , K
3 , b , E
What can I do in Linq (as I'm using Entity Framework) to get the following:
1 , x , G
1 , y , H
2 , z , J
2 , a , K
3 , b , E
You get the idea, I can do it in SQL just fine with the following:
Select Col 1, Col 2, Col 3
from Table
group by Col 1, Col 2, Col 3
No Idea how to do it in code as I can only find a way to do a distinct on one column.
Try this :
var Result = Context.Table.Select(C =>
new {
Col1 = C.Col1,
Col2 = C.Col2,
Col3 = C.Col3 }).Distinct();
Or alternately :
var Result = Context.Table.GroupBy(G=> new { G.Col1, G.Col2, G.Col3 })
.Select(C => new {
Col1 = C.Key.Col1,
Col2 = C.Key.Col2,
Col3 = C.Key.Col3
});
You could also use group by in linq on multiple fields:
myList.GroupBy(x=>new {x.Col1,x.Col2,x.Col3}).Select(x=>x.First()).ToList();
It is simple as, if you have only these three columns in the table.
var result = Context.Table.Distinct();
This will return your desired result.
If you have more columns then you can try as #Saeed Amiri stated in his answer.
#Kundan Singh Chouhan's alternative will give you the exact same sql query, which you state in your question

Resources