I want to return unique values from a data store using just a rule and query. Th

I want to return unique values from a data store using just a rule and query. This is what I have so far but I can't seem to figure out how to leverage the target field array. for the union function to operate on.
=union(todatasubset(rule!GetAllLrules().PUB),todatasubset(rule!GetAllrules().PUB))
So the .PUB part delivers the data sub set how do I then navigate to the field within it?
Ideas and outright solutions most welcome.
Thanks, James

OriginalPostID-147436

OriginalPostID-147436

  Discussion posts and replies are publicly visible

  • 0
    Certified Lead Developer
    Can you clarify a bit? Off the top of my head:
    1) why are you calling todatasubset() on the rule outputs?
    2) what is the sub-field you're trying to get the unique values of?
  • I was under the impression todatasubset was required in order to instantise the data for the rest of my expression, in turn allowing me to target the field I wanted to operate on.
    So my data set is quite simple, three columns with the primary key exposed for manipulation purposes. The fields are id (int), pub (text) and class (text). It is the pub field I want returned which I then want to execute union against in order to strip all duplicates.
    Does this give a better use case?
  • 0
    Certified Lead Developer
    Ah, I see. Sorry, your last sentence confused me a bit since it seemed like you were saying something else.
    AFAIK, there probably isn't a need to wrap the rule outputs in todatasubset() here - it's used to wrap a data output in some container data for use in other applications such as paging grids, as well as some corner case applications like forced sorting. If you're just after the raw data, basically rule!GetAllLrules().PUB, then I'd start off without that.

    I'm going to write this on the assumption that you're putting this in an expression rule to be called universally.
    First, I strongly recommend reducing your calls of the query rule since you're currently calling it twice. This is pretty easy to do by utilizing with() functionality.

    There are 2 equivalent approaches I will cover here - In option A, we load the whole CDT into a PV, then deal with the details. In option B, we load just the raw data of the .PUB field.

    A:
    with(
    local!cdtData: rule!GetAllLrules(),

    union(
    property( local!cdtData, "PUB", {} ),
    property( local!cdtData, "PUB", {} )
    ) /* we could just type "local!cdtData.PUB" in each of the above, but using Property() protects us against cases where the query returns empty */
    )

    B:
    with(
    local!PUBData: rule!GetAllLrules().PUB, /* we would want to use property() here, too, if there's any chance the query would return empty. otherwise it's about the same. */

    union( local!PUBData, local!PUBData )
    )

    I hope I'm not totally off-base with these - let me know if you need any further clarification etc.
  • Nice work mschmitt! I went for the second solution and that has worked a treat. I see your point about execution, the end result is faster and I can now deploy a rule instead of my process exec solution, which was neat but slower. Very tidy.

    Thank You!
  • 0
    Certified Lead Developer
    Glad to help, thanks for letting me know!

    FWIW, the reason I included the first approach is because, perhaps not here but elsewhere, it can sometimes be useful to access the other elements in the CDT after the query is run, whether used directly by the rule output or not. For instance, in another case, you could include a text rule input for "Field", and pass in the field name you want to return the uniques of; you could then pass that into the "property" function - so like this, you could use the same rule for "Pub" and "Class". Just for example.