I am creating an expression as follows:
SELECT(Parts[Part ID], IN([Kit], SELECT([Related Ordered Kits][Kit], [Processed?] <> true)))
I am trying to leverage already existing REF_ROWS for better performance.
When using this in an action on Form Save, it doesnโt appear to return any rows. So I began testing with the aid of Virtual Column (VC).
The VC is defined as a List of Ref Type with the base table = โPartsโ. Part ID is the Parts table key column.
In the Detail view, the VC shows as below named โTest Kit Countโ - indicates 4 rows but no rows are displayed
Clicking on the โViewโ button, the correct Parts_Inline view is being used but again no rows displayed. This same view is used elsewhere with a REF_ROWS column without issue so I donโt think it is a view problem.
If I change VC List base type from Ref to text, the 4 Part ID values are properly listed in the view.
However, if I click the Edit button to go into the Form and simply click Save, when the app returns to the Detail view the VC (base type as text) is blank initially. Waiting for few seconds, without touching anything else, the VC will update to the 4 values again as shown above.
What am I missing?
Why is the initial expression, when used in an action returning no rows?
Why, when placing the expression in a VC does it show no rows in the inline view?
And why, when the base type is text, does the VC blank out after a Save and then update again with the correct values?
Iโm not a fan of the Related โฆ columns because their behavior is seemingly inconsistent, just as youโre seeing.
Remember, the Related โฆ columns are virtual, so only update within a form view, when the row is updated by an action, or during a sync. Somehow, IsPartOf can also trigger an update, but itโs not clear to me how that works.
When you see that initial empty value, then a correction after a few moments, that says to me a sync happened behind the scenes.
I just avoid using Related โฆ columns.
If a child record of the table that has this marked as โTrueโ is updated, then a re-calc of the parent level is triggered - or itโs supposed to.
This level of integration is buggy.
I would never do anything like thisโฆ
I see what youโre trying to do, but you need to split things into different chunks.
For instance:
Take your de-reference list and make that itโs own column
[Related Order Kits][Kit]
But, since you want only the ones that are not processed - first, create a slice that represents these, then make your ref_rows use that instead of the root table.
This then leaves you with a list of all the [Related Incomplete Kits][Kit] in a single column - or in other words: โa list of all the [kit] values for each incomplete kit.โ
To get your actual result, a list of all the [Part ID]s for the kits that have yet to be processedโฆ
Then you can use the following Incomplete_Kits[Remaining_Parts] to pull a list of all the โlists of partsโ - which you need to specially deal with by using SPLIT() to transform that into a regular โlist of part IDs.โ
SPLIT(Incomplete_Kits[Remaining_Parts], " , ")
That will give you a LIVE list of all the remaining part IDs from all the records inside the slice.
First, I want to thank both of you for your input. It is always appreciated and you both have given me some great insight to something I have struggled with for a while but just never put time into trying to dig deeper until now. Thank you!!
I ended up changing the SELECT to operate against the table directly.
Is this only because its not supported well? The parser passes the expression which implies itโs supported. You CAN create a VC with the desired dereferenced column that proves to me the implementation is supported. The two should work together.
It seems to me that AppSheet has provided the capabilities to use Related lists in expressions and since they are just lists why not be able to use them, and any implemented Related list dereference functions, anywhere lists are supported.
My SoapBox
My main goal here is to increase performance. Related lists are a needed list that many apps will need to operate on frequently. They are the most efficient way to get at that data because, well, they are already there with desired items. It would be greatly beneficial to be able to use them anywhere lists can be or are expected.
Adding more VCโs and Slices and writing more SELECT statements not only decrease overall app performance but also increase develop maintenance.
That inference is entirely wrong.
How so?
The expression parser will โvalidateโ plenty of expressions that wonโt behave as intended. The parser is not purpose-built for AppSheet. Itโs an Excel formula parser thatโs been tweaked to recognize AppSheet-isms, and itโs not all that great at it.
The reason all the documentation I write quotes text values is because the parser recognizes Excel functions and reserved words and will try to validate their syntax, producing an error if the expression doesnโt match Excelโs expectations.
Date
and Time
are Excel functions, but also common column names. When an unquoted column of either of those names is used with (e.g.) LOOKUP(), the parser will complain because the Excel functions must have arguments, even though LOOKUP() isnโt even expecting an expression.
If I recall correctly, the parser recognizes and validates both of the Excel functions N() and T(), neither of which exist in AppSheet.
There are several situations where extraneous or missing punctuation is entirely overlooked by the parser. In some of those cases, a huge chunk of the expression is just silently ignored.
Got it! The AppSheet syntax is fairly unique (at least to anything Iโve seen) I thought it was a custom parser they had full control over.
They do have control of it, but itโs not perfect.
The parser will throw errors where there are none and will validate expressions that donโt work for any number of reasons. My favorite is setting a ref column it expects the result to be type ref but you grab the base type of the key for that reference table. Throws an error but is completely accepted and functions just fine.
Dont know if that bug still exist but it did a few weeks ago.
When you see this, some piece of meta-data is off; typically it will be that at some point the โrefโ status of the data is lost.
If I were you: from here I do what Iโm suggesting and split things out into separate columns.
This is a bug dealing with the โbackground final sync after all the syncsโ - hard to explain.
Basically, after all the records that need to be pushed into the cloud are pushed, the app goes through a final sync to finalize all the values.
Then, if youโre not paying attention youโll miss it, another sync happens (you can spot this by watching the old sync button (if you have it on)). Itโs this background sync that has been causing apps on the more complicated level to spawn errors of some kind.
Itโs been the bane of an app I built for a research institute: things are pretty complex in that app, and this is a regular issue we have.
I understand. I guess the bug is that the VC is physically blanked out instead of simply being overwritten - even with the same values(s)?
I can completely understand where youโre coming from @WillowMobileSystems, and youโre thinking about things in the right way - now we need to add in a whole-nother layer: the calculation steps.
This is where the real meat and potatoes of your appโs sync time comes in.
If youโve got the following in a VC:
Select(Parts[PartID], in([PartID], Select([Related Records][Column_A], [Column_B] = โSome Valueโ)))
the following will happen:
First the list of related records needs to be created
Select(ChildTable[ChildID], [Parent_Ref] = [_Thisrow].[ParentID])
Now that the system has the base child lists, next we need to process your actual formula. The first part we need is the de-reference list of [Column_A] values - and since the de-ref list is included in a select formula, the additional conditions from that select are applied to this next step.
Select(Child_Table[Column_A], and(
in([ChildID], [_Thisrow].[Related Records]),
[Column_B] = โSome Valueโ
))
Thatโs how many records the system is having to deal with, just in that one VC.
To my suggestion of the slice:
If you move the [Column_B] = โSome Valueโ into a slice, instead of that being calculated for each record, instead it only processes once - when the slices are calculated - then that list is stored in the slice.
To the point of moving the de-reference list into itโs own column:
Hope I made some sense in there; this is a really complicated and dense topic. Iโm putting together a video now about variable handling, should be out in a few weeks.
Great write-up! Kudos for taking the time. I do totally get what you are driving at but I think there is a fundamental mis-understanding in how the table scanning works with regards to Ref values - at least to the best of my understanding.
First, just for clarification, this kind of analysis is usually measured in โoperationsโ using Big O notation. There is a whole section of study within the Computer Science industry determining the performance of code and coding algorithms. They use Big O notation to compare one algorithm to another to find the most performant.
Now, how does table scanning work with regards to Ref/key values?
Tables are typically indexed by the key value. Simply put, this means that a table row can be found within a single operation when the row key is known - no full scan required. When there is a list of Ref/key values, you can think of each row as being retrieved directly from the host table - when needed.
This is why Ref columns REQUIRE the usage of row keys in the constructed list.
It is also why I started this postโฆbecause using Related lists, and even Ref columns, is MUCH more efficient than having to rely on tables scans.
There is a caveat to all this, it all depends on how AppSheet has implemented their logic. I am fairly confident in saying that a lot of their implementation does indeed take advantage of indexing otherwise our apps would be tremendously slow.
Good discussion!
Hi @MultiTech_Visions did you have the time to do this video?
@Fabian no
Itโs been on my list this whole time, and Iโve actually tried a few times - but every time I try and come up with some sort of way to communicate all this cohesively in a videoโฆ it just doesnโt come across.
Itโs still on my list, thanks for the reminder - Iโll take another crack at it.
User | Count |
---|---|
43 | |
29 | |
23 | |
20 | |
13 |