Search code examples
sql-serverxmlsqlxml

xml query with more than one condition


It is my sql data :

<ArrayOfFlowDetailParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <FlowDetailParameters>
    <DepartmentId>23</DepartmentId>
    <UserId xsi:nil="true" />
    <Username />
    <FullName />
    <ConfirmDateTime xsi:nil="true" />
    <Comment />
    <Status>Pending</Status>
    <AttachmentId />
  </FlowDetailParameters>
  <FlowDetailParameters>
    <DepartmentId>22</DepartmentId>
    <UserId xsi:nil="true" />
    <Username />
    <FullName />
    <ConfirmDateTime xsi:nil="true" />
    <Comment />
    <Status>Pending</Status>
    <AttachmentId />
  </FlowDetailParameters>
  <FlowDetailParameters>
    <DepartmentId>7</DepartmentId>
    <UserId xsi:nil="true" />
    <Username />
    <FullName />
    <ConfirmDateTime xsi:nil="true" />
    <Comment />
    <Status>Pending</Status>
    <AttachmentId />
  </FlowDetailParameters>
  <FlowDetailParameters>
    <DepartmentId>18</DepartmentId>
    <UserId xsi:nil="true" />
    <Username />
    <FullName />
    <ConfirmDateTime xsi:nil="true" />
    <Comment />
    <Status>Pending</Status>
    <AttachmentId />
  </FlowDetailParameters>
</ArrayOfFlowDetailParameters>

i want to find a node i mean FlowDetailParameters with 2 conditions it means with departmentid=23 and status=pending .

Here is my query :

SELECT
    Requests.* 
FROM
    Requests
WHERE
    (@organizationid IS NULL OR OrganizationId = @organizationid) 
    AND (@DetailStatus IS NULL 
         OR (EXISTS (SELECT *
                     FROM Requests.FlowDetailParameter.nodes('/ArrayOfFlowDetailParameters/FlowDetailParameters/DepartmentId') as Parms(DepartmentId)
                     WHERE DepartmentId.value('.', 'bigint') = @departmentId) 
         AND EXISTS (SELECT *
                     FROM Requests.FlowDetailParameter.nodes('/ArrayOfFlowDetailParameters/FlowDetailParameters/Status') as Parms(Status)
                     WHERE Status.value('.', 'nvarchar(max)') = @DetailStatus)))

but my query finds the nodes with departmentid=23 or status=pending


Solution

  • You can apply search criteria to subnodes directly in your XQuery:

    declare @t table (XData xml);
    
    declare @StatusValue varchar(50) = 'Pending',
        @DepartmentId int = 23;
    
    insert into @t (XData)
    values (
    N'<ArrayOfFlowDetailParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <FlowDetailParameters>
        <DepartmentId>23</DepartmentId>
        <UserId  />
        <Username />
        <FullName />
        <ConfirmDateTime  />
        <Comment />
        <Status>Pending</Status>
        <AttachmentId />
      </FlowDetailParameters>
      <FlowDetailParameters>
        <DepartmentId>22</DepartmentId>
        <UserId  />
        <Username />
        <FullName />
        <ConfirmDateTime  />
        <Comment />
        <Status>Pending</Status>
        <AttachmentId />
      </FlowDetailParameters>
      <FlowDetailParameters>
        <DepartmentId>7</DepartmentId>
        <UserId  />
        <Username />
        <FullName />
        <ConfirmDateTime  />
        <Comment />
        <Status>Pending</Status>
        <AttachmentId />
      </FlowDetailParameters>
      <FlowDetailParameters>
        <DepartmentId>18</DepartmentId>
        <UserId  />
        <Username />
        <FullName />
        <ConfirmDateTime  />
        <Comment />
        <Status>Pending</Status>
        <AttachmentId />
      </FlowDetailParameters>
    </ArrayOfFlowDetailParameters>');
    
    select a.c.query('.')
    from @t t
        cross apply t.XData.nodes('/ArrayOfFlowDetailParameters/FlowDetailParameters[
            ./DepartmentId[1]/text() = sql:variable("@DepartmentId")
            and ./Status[1]/text() = sql:variable("@StatusValue")
        ]') a(c);
    

    Also, since you will probably need this, I have also provided an example of how to parameterise such a query.