I’ve been doing some work today on filtering multi-select optionset fields in SQL 4 CDS and using the T-SQL endpoint, and I came across a few interesting quirks.
FetchXML
There are two specialised FetchXML operators for multi-select picklist fields: contain-values
and not-contain-values
. You can use these from Advanced Find or FetchXML Builder, and select all the values you’re searching for in one go:
In FetchXML this looks like:
<fetch> <entity name="account"> <attribute name="name" /> <attribute name="markmpn_multiselecttest" /> <filter> <condition attribute="markmpn_multiselecttest" condition="contain-values"> <value>1</value> <value>2</value> </condition> </filter> </entity> </fetch>
Somewhat surprisingly though, this will get accounts that have either of these values selected, rather than requiring both:
OData
What, you want to write an OData query directly instead of using FetchXML Builder to convert from FetchXML to OData for you? Well, if you insist, you can use the following syntax:
https://contoso.crm.dynamics.com/api/data/v9.1/accounts?$select=name,markmpn_multiselecttest&$filter=Microsoft.Dynamics.CRM.ContainValues(PropertyName='markmpn_multiselecttest',PropertyValues=['1','2'])
SQL
Behind the scenes the data is stored as a comma-separated list of numbers, so the example above is stored as:
Account Name | Multiselect Test |
---|---|
Account 1 | 1 |
Account 2 | 2 |
Account 3 | 1,2 |
This isn’t efficient to search, so another copy is also stored in a separate table with a full text index. This lets CDS convert the query above to the slightly verbose but efficient SQL (adapted example):
SELECT account.name, account.markmpn_multiselecttest FROM account INNER JOIN MultiSelectAttributeOptionValuesBase AS msj ON account.AccountId = msj.ObjectId AND msj.ObjectIdTypeCode = 1 AND msj.ObjectColumnNumber = 1234 WHERE CONTAINS(msj.SelectedOptionValues, '1 OR 2')
This is all well and good for on-premise systems, but what about online? With the preview TDS endpoint we can get filtered access to the SQL database, but unfortunately not to the special MultiSelectAttributeOptionValuesBase
table.
As the main multi-select picklist field does not have full-text indexing applied, you can’t use a query like:
SELECT name, markmpn_multiselecttest FROM account WHERE CONTAINS(markmpn_multiselecttest, '1 OR 2')
This will give the error:
Msg 40000, Level 16, State 1, Line 1
Cannot use a CONTAINS or FREETEXT predicate on table or indexed view 'FilteredAccount' because it is not full-text indexed.
We can get the results we want, but we need to write a less efficient version of the query:
SELECT name, markmpn_multiselecttest FROM account WHERE markmpn_multiselecttest = '1' OR markmpn_multiselecttest LIKE '1,%' OR markmpn_multiselecttest LIKE '%,1,%' OR markmpn_multiselecttest LIKE '%,1' OR markmpn_multiselecttest = '2' OR markmpn_multiselecttest LIKE '2,%' OR markmpn_multiselecttest LIKE '%,2,%' OR markmpn_multiselecttest LIKE '%,2'
For each value we want to search for we need to include 4 checks:
- The only selected value (
= '1'
) - The first value (
LIKE '1,%
) - A value in the middle (
LIKE '%,1,%
) - The last value (
LIKE '%,1'
)
However, in the next version of SQL 4 CDS I will be including support for writing a query in this format and converting it to the corresponding FetchXML:
SELECT name, markmpn_multiselecttest FROM account WHERE CONTAINS(markmpn_multiselecttest, '1 OR 2')
Hi, I was trying to filter on multi-select list on related entity, but I get error message that primary entity does not contain property named “lookupField/multiselectFieldname”. So this doesn’t seem to work with related entities, when multi-select field is on related entity. Or am I missing something?
No, I believe the PropertyName setting on the function in OData can only reference properties on that entity, not related entities
The following fragment works for me – I couldn’t get the condition=”contain-values” to work – coming back as invalid XML in XrmToolBox FetchXML Tester.
862800004
Unfortunately any xml is stripped by the blog engine, could you use the HTML encoding option on FetchXML Builder to encode your query so you can share it here please?
Hello Mark.
I am an admirer of your work.
Please help me:
I use power portals.
In the form for anonymous users, I added a search field. When clicking on the search, the records are displayed. Select button is available. But, it doesn’t click. It does not select the record.
I use the table of accounts.
What is the problem?
Thanks
Sorry, I’m no expert on Power Portals. I’d suggest you ask over at the community forums https://powerusers.microsoft.com/t5/Microsoft-Power-Pages-Community/ct-p/MPPCommunity