Choice() in dataview evaluates all conditions (expected behaviour?)

What I’m trying to do

Im trying to execute a choice function nested inside of a other choice function. The first choice functions evaluates whether the target is empty and returns “No value” if thats true and execute the the second choice() if false. The second choice() will check for the value of the target and will decide what to do next based on that value.

The problem im running into is that dataview will evaluate both conditions and returns “no implementation found for ‘null / number’” if the target value is null, instead of returning “No value”.

Things I have tried

In the first image the properties and error message is visible, in the second image the queries.

The second query is the exact same as the third query, except for the true statement in the second choice function. In my eyes it shouldn’t evaluate the second choice() true statement and therefore should not give me the error. Is this a bug or am I not understanding the function correctly.

I’ve found someone running into a similar problem but he ended up changing the query. Something that doesn’t work for this case and does not adress the ?bug.

Gives the same error.

1 Like

I reckon this behavior is due to how dataview parses the query, and that this can’t be easily countered. I tried with an even simpler statement of choice(false, dateEnd / 2, "hmmm"), and it failed. So I do believe this is something you need to handle a different way.

One such way could either be to require that dateEnd always has a value, as in doing something like WHERE dateEnd in your query, but I reckon that doesn’t match up with the rest of your query. Another option is to give the wrongful entry a “legal” value, even if it doesn’t exist. This can be done using something like default() in constructs like: choice(false, default(dateEnd, 1) / 2, "Hooray"), which would reliably produce “Hooray”.

A more constructive variant would of course be to do: choice(!dateEnd, "No value", default(dateEnd, 1) / 2). In this case if the dateEnd actually had a value, it would be used instead of the 1, and your query would behave. If no dateEnd it would use the 1 value, which would produce some random value, but it’ll not be used due to the choice function.

That would work for the query in the example, but is unfortunately too limited for the use case I had in mind. I guess I should resort to a JS query.

Is this behaviour something I should report to the repository or is parsing something that can’t easily be changed?

I don’t think there is any point in reporting it, as that parsing is rather complex, and the author is focusing on the heir of dataview, namely the datacore plugin.

Present more of the use case, and we could possibly help you further with your query.

1 Like

What im trying to make is a field that calculates the accuracy of the estimated time compared to the actual time it took to finish a project. The rangeEnd marks the end of the project and thus will be empty until completed. The formula below doesn’t work if rangeEnd is empty.

choice(
    !rangeEnd,
    "No value",
    (choice(
      (round(((rangeEnd - rangeBegin).day / ((rangeBegin + durationEstimate) - rangeBegin).day) * 100, 1) > 100),
      (round((((rangeBegin + durationEstimate) - rangeBegin).day / (rangeEnd - rangeBegin).day) * 100, 1) + "%"),
      (round(((rangeEnd - rangeBegin).day / ((rangeBegin + durationEstimate) - rangeBegin).day) * 100, 1) + "%")
    ))
  )

I don’t think I can use a single formula for the accuracy calculation, since it would give a score greater than 100% if the project takes longer than the estimated time.

A typical project will have these fields:

---
durationEstimate: 5 weeks
rangeBegin: 2023-06-15
rangeEnd:
---

So, for the calculation to not fail the range end needs to be larger than the rangeBegin, but since we’re not going to use it anyways it can be whatever.

FLATTEN default(rangeEnd, rangeBegin + dur("1 day")) as rE
FLATTEN choice(
    !rangeEnd,
    "No value",
    (choice(
      (rE - rangeBegin).day / ((rangeBegin + durationEstimate) - rangeBegin).day) * 100, 1) > 100),
      (round((((rangeBegin + durationEstimate) - rangeBegin).day / (rE - rangeBegin).day) * 100, 1) + "%"),
      (round(((rE - rangeBegin).day / ((rangeBegin + durationEstimate) - rangeBegin).day) * 100, 1) + "%")
    ))
  ) as rangeCalc

Here if rangeEnd is defined we move it over to rE and calculations are good, and if not defined we set it to a value allowing the calculation/parsing to be carried out, but since it’s still undefined we get the wanted result of “No value”.

1 Like

Thank you, this works. It’s smart to realize that rangeEnd could be whatever, as long as the calculation will not be faulty. A good example of adapting to the the circumstances.

I just noticed that of the four question I have posed (with some time between them) on this forum, you’ve answered them all. I want to thank you for the service you’ve been offering to the community. Cheers!

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.