inner join not working in dynamics crm query - sql

I am working in a project and I find that they do a query like this:
LinkEntity link = LinkEntity("table1", "account", "table1acountid", "accountid", JoinOperator.Inner)
link.LinkCriteria.AddCondition("accountid", ConditionOperator.Equal, Id);
the relation between table1 and account is 1: N ( we have a lookup to account in table1 form)
The result of the query is always null but when I change Inner with Leftouter, it works.
Is that query correct with inner join? In which case is it supposed to return records of table1?

The condition you add is not necessary, if used to only return accounts associated with table1, that comes implicitly from the LinkEntity statement.
I guess you are missing a new directive on the first line too.
Suggest you use FetchXML Builder for XrmToolBox to componse the query, which can then be converted to QueryExpression code.
I assume this is the query you want (adding a few attributes to return etc)
<fetch >
<entity name='' >
<filter>
<condition attribute='accountid' operator='eq' value='Id' />
</filter>
<link-entity name='table1' from='table1accountid' to='accountid' link-type='inner' />
</entity>
</fetch>

Related

How do I get a value from XML column in SQL?

So, I have a table with a large chunk of data stored in XML.
The partial XML schema (down to where I need) looks like this:
<DecisionData>
<Customer>
<SalesAttemptNumber />
<SubLenderID>IN101_CNAC</SubLenderID>
<DecisionType>Decision</DecisionType>
<DealerID />
<CustomerNumber>468195994772076</CustomerNumber>
<CustomerId />
<ApplicationType>Personal</ApplicationType>
<ApplicationDate>9/16/2008 11:32:07 AM</ApplicationDate>
<Applicants>
<Applicant PersonType="Applicant">
<CustNum />
<CustomerSSN>999999999</CustomerSSN>
<CustLastName>BRAND</CustLastName>
<CustFirstName>ELIZABETH</CustFirstName>
<CustMiddleName />
<NumberOfDependants>0</NumberOfDependants>
<MaritalStatus>Single</MaritalStatus>
<DateOfBirth>1/1/1911</DateOfBirth>
<MilitaryRank />
<CurrentAddress>
<ZipCode>46617</ZipCode>
Unfortunately, I am unfamiliar with pulling from XML, and my google-fu has failed me.
select TransformedXML.value('(/DecisionData/Customer/Applicants/Applicant PersonType="Applicant"/CurrentAddress/ZipCode/node())[1]','nvarchar(max)') as zip
from XmlDecisionInputText as t
I believe my problem lies with the portion that goes Applicant PersonType="Applicant", but am unsure how to deal with it.
Thanks for any help.
The xpath in its simplest form would be:
TransformedXML.value('(//ZipCode)[1]', 'nvarchar(100)') AS zip
This will find the first ZipCode node anywhere inside your document. If there are multiple, just be specific (as much as you want but not any more):
TransformedXML.value('(/DecisionData/Customer/Applicants/Applicant[#PersonType="Applicant"]/CurrentAddress/ZipCode)[1]', 'nvarchar(100)') AS zip
DB Fiddle
If there are MULTIPLE applicants, you can use a CROSS APPLY
Example
Select A.ID
,B.*
From XmlDecisionInputText A
Cross Apply (
Select PersonType = x.v.value('#PersonType','VARCHAR(150)')
,CustLastName = x.v.value('CustLastName[1]','VARCHAR(150)')
,CustFirstName = x.v.value('CustFirstName[1]','VARCHAR(150)')
,ZipCode = x.v.value('CurrentAddress[1]/ZipCode[1]','VARCHAR(150)')
From XmlDecisionInputText.nodes('DecisionData/Customer/Applicants/*') x(v)
) B

How do I modify a xml attribute in a xml field of a Sql Server table

I'm trying to update a XML column in a SQL Server table using the
XML.modify replace value of (XML DML)
With the below XML example, is there a way I can replace all vendorId with value 1 into another value? From the documentation in http://technet.microsoft.com/en-us/library/ms190675.aspx it looks like I need to specify the record index for that. But in my case, there would be multiple records within the xml and I would not know the order it would be in.
<LineItems>
<LineItem productId="48" invId="1573" quantity="1" id="1" vendorId="1022" price="1350.0000" cost="450.0000" discount="0" acqu="2" />
<LineItem productId="1" invId="0" quantity="1" id="2" vendorId="1" price="400" cost="0" discount="0" />
<LineItem productId="46" invId="1574" quantity="1" id="3" vendorId="1022" price="789.0000" cost="263.0000" discount="0" acqu="4" />
<LineItem productId="1" invId="0" quantity="1" id="4" vendorId="1" price="300" cost="0" discount="0" />
</LineItems>
Please advice.
Thanks!
You have to use a loop and update one value at a time.
while #XML.exist('/LineItems/LineItem[#vendorId = "1"]') = 1
set #XML.modify('replace value of (/LineItems/LineItem[#vendorId = "1"]/#vendorId)[1] with "2"' )
SQL Fiddle
A version that updates a XML column in a table would look like this.
while exists(
select * from T
where T.XMLColumn.exist('/LineItems/LineItem[#vendorId = "1"]') = 1
--and [some other condition]
)
begin
update T
set XMLColumn.modify('replace value of (/LineItems/LineItem[#vendorId = "1"]/#vendorId)[1] with "2"')
where T.XMLColumn.exist('/LineItems/LineItem[#vendorId = "1"]') = 1
--and [some other condition]
end
SQL Fiddle
If you need to replace a constant string to another one, I advise you yo use REPLACE function and perfom it on string.
DECLARE #XML XML /*your xml value*/
SELECT REPLACE(CONVERT(NVARCHAR(MAX),#XML),'vendor="1"','"vendor="2"')
In many cases it's much easier then do it in xml-style.

Extracting XML data in SQL - too many cross apply statements

I have an xml document containing details from a Statement:
<Statement>
<Id />
<Invoices>
<Invoice>
<Id />
<Date />
<AmountDue />
etc.
</Invoice>
<Invoice>
<Id />
<Date />
<AmountDue />
etc.
</Invoice>
<Invoice>
<Id />
<Date />
<AmountDue />
etc.
</Invoice>
</Invoices>
</Statement>
This works fine for the Statement specific details:
SET #statementId = #xml.value('(Id)[1]', 'UNIQUEIDENTIFIER');
but it requires a singleton, and only returns the first value. I need ALL of the values for the invoices, not just the first so a singleton won't work.
I am able to get the information out using cross apply statements like this:
SELECT
#statementId AS STATEMENT_ID
Id.value('.', 'uniqueidentifier') AS INVOICE_ID
Date.value('.', 'smalldatetime') AS INVOICE_DATE
Due.value('.', 'decimal') AS INVOICE_AMOUNT_DUE
FROM #xml.nodes('Statement') A(S)
cross apply S.nodes('Invoices/Invoice') B(InvoiceD)
cross apply InvoiceD.nodes('Id') C(Id)
cross apply InvoiceD.nodes('Date') D(Date)
cross apply InvoiceD.nodes('AmountDue') E(Due)
This returns an Id, date, and amount from each Invoice in the Statement - perfect.
My problem comes when I try to extract all of the invoice details. I currently have seven cross apply statements and I got the following message:
"The query processor ran out of internal resources and could not
produce a query plan. This is a rare event and only expected for
extremely complex queries or queries that reference a very large
number of tables or partitions. Please simplify the query. If you
believe you have received this message in error, contact Customer
Support Services for more information."
What I want to do is have one cross apply for the Invoice and narrow down the exact field in the select statement, but unless I use '.' I must make the statement return a singleton and I don't get all of the data that I need.
I have done some research about specifying a namespace within the select statement, but all of the examples set the namespace to be an http address instead of a node in an xml document and I haven't gotten anything to return yet using this approach.
The result I'm looking for is something like this, but with more Invoice Details:
STATEMENT_ID INVOICE_ID INVOICE_DATE INVOICE_AMOUNT_DUE ...
Statement-1-Id Invoice-1-Id Invoice-1-Date Invoice-1-AmountDue ...
Statement-1-Id Invoice-2-Id Invoice-2-Date Invoice-2-AmountDue ...
Statement-1-Id Invoice-3-Id Invoice-3-Date Invoice-3-AmountDue ...
Where should I go from here?
EDIT: I removed some unnecessary information. Getting all of the invoice-specific details is my goal here.
select #XML.value('(Statement/Id/text())[1]', 'uniqueidentifier') as StatementId,
T.N.value('(Id/text())[1]', 'uniqueidentifier') as InvoiceId,
T.N.value('(Date/text())[1]', 'smalldatetime') as InvoiceDate,
T.N.value('(AmountDue/text())[1]', 'decimal') as AmountDue
from #XML.nodes('/Statement/Invoices/Invoice') as T(N)
.nodes will shred your XML to rows so that each row T.N is pointing to an Invoice node of its own. On that node there is only a single Id node so fetching the value specifying a singleton Id[1] works.
You can use Id[1] or (Id/text())[1] but the latter will give you a more efficient execution plan.

Finding the relevant records using XQuery/XPath

I'm very very new to XQUERY/XPATH :) so I could very well be going about this the wrong way. I have a customer object serialized and stored in a database column in the following format.
<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Addresses>
<AddressBlock>
<AddressLine1>1234 SomeStreet Ave.</AddressLine1>
<City>SomeCity</City>
<State>SomeState</State>
<Zipcode>SomeZip</Zipcode>
</AddressBlock>
<AddressBlock>
<AddressLine1>5678 SomeOtherStreet Ave.</AddressLine1>
<City>SomeOtherCity</City>
<State>SomeOtherState</State>
<Zipcode>SomeOtherZip</Zipcode>
</AddressBlock>
</Addresses>
</Customer>
I'm looking for a way to select this record if addressline1 and city in the same addressblock contains certain keywords. I have the following statement that almost does what I'm looking for.
select *
from users
where [UserData].exist('/Customer/Addresses/AddressBlock/AddressLine1/text()[contains(upper-case(.),""SOMESTREET"")]')=1
and [UserData].exist('/Customer/Addresses/AddressBlock/City/text()[contains(upper-case(.),""SOMECITY"")]')=1"
My only problem is this statment will also return the record if the first addressblock contains the addressline1 and the second addressblock contains the city.
You have to test both conditions in the same XQuery.
select *
from users
where [UserData].exist('/Customer/Addresses/AddressBlock
[contains(upper-case(AddressLine1[1]),"SOMESTREET") and
contains(upper-case(City[1]),"SOMECITY")]')=1

Solr DIH dynamic filed name & convert value

I have a working solr with DIH now i need to add multi rows which is ONE to MANY relationship with the solr indexed doc
TABLE:
ID:int PK
post_id:int FK
name:string
value:text
type:(int|string)
i need to insert all rows based on FK (post_id) into solr doc with dynamic name and convert value based on type
SELECT name,value,type FROM TABLE WHERE post_id='${post_entity.id}';
loop
insert into solr fieldname: meta_{$name} value: if type int cast to int else just value
end loop
Anyone knows how to do this?
Not sure if you have the answer yet, but my understanding is you need to create multiple entity tabs in the data handler document, one for each new multi-value field you want to add, and indicate the ID from the root document. Look at this example:
In the DataHandler.xml file:
<dataConfig>
<dataSource name="jdbc" driver="org.postgresql.Driver" url="jdbc:postgresql://localhost/bedrock" user="postgres" password="test" batchSize="1000" readOnly="true" autoCommit="false" transactionIsolation="TRANSACTION_READ_COMMITTED" holdability="CLOSE_CURSORS_AT_COMMIT" />
<document name="doc-a">
<entity name="employee-root" datasource="jdbc" pk="id" query ="
select
a.id as id,
a.name as name,
a.dept as dept,
a.jobtitle as jobtitle,
a.last_change as last_change
from employee a
"
transformer="RegexTransformer,DateFormatTransformer,TemplateTransformer">
<field column = "id" />
<field column = "name" />
<field column = "dept" />
<field column = "jobtitle" />
<entity name="employee-hobby" datasource="jdbc" query ="
select
employee_hobby as features
from employee_hobby
where employee_id = ${employee-root.id}
"
transformer="RegexTransformer,DateFormatTransformer,TemplateTransformer">
<field column = "features" />
</entity>
</entity>
</document>
i think i can use DIHCustomTransformer to invoke a function but i am not sure yet
http://wiki.apache.org/solr/DIHCustomTransformer
any enlightenment will be appreciated