Skip to main content
Announcements
Introducing Qlik Answers: A plug-and-play, Generative AI powered RAG solution. READ ALL ABOUT IT!
cancel
Showing results for 
Search instead for 
Did you mean: 
smarties
Contributor II
Contributor II

Slow to load code that implements Exists() with a wildcard

Hi,

I have some code that is functionally correct, but it's slow to load - 5 mins. The code is an attempt to provide the functionality of Exists() with a wildcard. Any thoughts on how to speed-up  with a different approach would be appreciated.

The field list 'TargetDevice' is some tens of parts. The field list 'RUPI' is 25k parts. A 'TargetDevice' is the front portion of a 'RUPI'. How much is an unknown, hence the need for the * wildcard. The desired outcome is a table that maps 'TargetDevice' to 'RUPI'.

Thanks.

Code that works, but is slow to load ...

Mapping:
Load *
Inline
[
TargetDevice, RUPI
];

For Each vTargetDevice in FieldValueList('TargetDevice')

Let vFound = False();

For Each vRUPI in FieldValueList('RUPI')

If '$(vRUPI)' Like '$(vTargetDevice)*' Then

Concatenate(Mapping)
Load *
Inline
[
TargetDevice, RUPI
$(vTargetDevice), $(vRUPI)
];

Let vFound = True();

End If;

Next vRUPI;

If not vFound Then

Concatenate(Mapping)
Load *
Inline
[
TargetDevice, RUPI
$(vTargetDevice), NotFound
];

End If;

Next vTargetDevice;

 

Labels (1)
4 Replies
rwunderlich
Partner Ambassador/MVP
Partner Ambassador/MVP

I would use a "wildcard mapping table" approach. See this downloadable example. 

Qlikview Cookbook: Mapping With Wildcards https://qlikviewcookbook.com/recipes/download-info/mapping-with-wildcards/

For your case, it would look something like this:

wildmap: 
LOAD
  TargetDevice as Key,
  '*' & TargetDevice as Label
from ....;

_MapExpr:
LOAD
  'pick(wildMatch($1,' & chr(39)
  & concat(Key, chr(39) & ',' & chr(39), FieldIndex('Key', Key))
  & chr(39)
  & '), ' & chr(39)
  & concat(Label, chr(39) & ',' & chr(39), FieldIndex('Key', Key))
  & chr(39) & ')' as MapExpr
RESIDENT wildmap
;
LET vMapExpr = peek('MapExpr', -1);
DROP TABLE _MapExpr; 
DROP TABLE wildmap;  

Facts:
LOAD
  $(vMapExpr(RUPI)) as TargetDevice,

  ...
from ...;

-Rob
http://www.easyqlik.com
http://masterssummit.com
http://qlikviewcookbook.com

 

oskartoivonen
Partner - Contributor III
Partner - Contributor III

Looping through each TargetDevice and RUPI combination is probably the slowest approach in Qlik. You want to load the RUPI list once with a LOAD-statement, and check each RUPI for Target Device hits with a search.

Maybe this script does what you need? It looks a bit wonky because we're using dynamic script, but should execute over a 25k table swiftly. The Test-field can be used directly in the WHERE statement to filter the rows with no hits.

 

TargetDevice:
LOAD * INLINE [
	TargetDevice
	A
	B
	C
];

let vL.WildMatch = ;

for each vL.TargetDevice in FieldValueList('TargetDevice')
	if Len('$(vL.WildMatch)') = 0 then
		let vL.WildMatch = '''$(vL.TargetDevice)*''';
	else
		let vL.WildMatch = '$(vL.WildMatch), ''$(vL.TargetDevice)*''';
	endif
next

Test:
LOAD
	RUPI,
	WildMatch(RUPI, $(vL.WildMatch)) as Test,
	Pick(WildMatch(RUPI, $(vL.WildMatch)),
		$(vL.WildMatch)
	) as Test2,
	Replace(Pick(WildMatch(RUPI, $(vL.WildMatch)),
		$(vL.WildMatch)
	), '*', '') as Test3
INLINE [
	RUPI
	A100
	B200
	C300
	D400
];

 

Result (Test3 is what you want):

oskartoivonen_0-1662326849175.png

 

smarties
Contributor II
Contributor II
Author

Thank you @rwunderlich and @oskartoivonen. It's taken me a while to get my head round what you've provided. New techniques learnt. 😊

MarcoWedel

maybe another solution could be:

 

MarcoWedel_0-1662819948481.png

 

// some random test data

tabTargetDevice:
LOAD Left(KeepChar(Hash128(Rand()),'ABCDEFGHIJKLMNOPQRSTUVWXYZ'),Ceil(Rand()*3)+1) as TargetDevice
AutoGenerate 1000;

tabRUPI:
LOAD Left(KeepChar(Hash256(Rand()),'ABCDEFGHIJKLMNOPQRSTUVWXYZ'),Ceil(Rand()*8)+4) as RUPI
AutoGenerate 100000;



// Mapping

mapTargetDevice:
Mapping
LOAD Distinct
     TargetDevice,
     '@FoundOne@'&TargetDevice&'@RightUpToHere@'
Resident tabTargetDevice;

tabMapping:
LOAD Distinct
     RUPI,
     TextBetween(RUPIMapped,'@FoundOne@','@RightUpToHere@',1) as TargetDevice
Where RUPIMapped like '@FoundOne@*';
LOAD RUPI,
     MapSubString('mapTargetDevice',RUPI) as RUPIMapped
Resident tabRUPI;

 

 

hope this helps

Marco