【问题标题】:SQL Server WHERE clause XPath with multiple nodes and conditions具有多个节点和条件的 SQL Server WHERE 子句 XPath
【发布时间】:2017-01-10 15:50:58
【问题描述】:

我在 SQL Server 的表列中有这个 XML:

<root>
    <Request>
        <RequestData>
            <VendorLeadList>
                <VendorLeadItem>
                    <CampaignOfferTypeID>REN</CampaignOfferTypeID>
                    <LeadDispositionID>Lead</LeadDispositionID>
                    <Jurisdiction>NY</Jurisdiction>
                    <FirstName>Shikasta</FirstName>
                    <LastName>Kashti</LastName>
                    <MessageId>1347_1483825159115_c8273</MessageId>
                </VendorLeadItem>
            </VendorLeadList>
        </RequestData>
        <DualMessageID/>
        <AzureBlobFile/>
        <AzureBlobImageList/>
    </Request>
</root>

我想查询与某些具有特定值的节点匹配的所有记录。例如,我想要 LeadDispositionID=LeadJurisdiction=NYCampaignOfferTypeID=RENMessageId 元素存在的所有记录(无论值是什么。)

我试过了,但它不起作用(没有错误但条件不匹配,它返回其他记录):

SELECT TOP 10 *
  FROM [Messages]
  WHERE PayLoadXml.exist('//LeadDispositionID[.="Lead"] and //CampaignOfferTypeID[.="REN"] and //Jurisdiction[.="NY"] and //MessageId') = 1
  ORDER BY ID DESC

知道我做错了什么吗?

【问题讨论】:

  • 你的 xpath 在这里绝对没问题。我会用PayLoadXml.exist() 函数在那里侦察。
  • @Granitosaurus 不,你不能简单地将节点与and...
  • @Shnugo 你是什么意思? and 是完全有效的 xpath,您可以像这样组合节点,xpath 将单独评估每个节点,如果匹配则返回 '1',否则返回 '0'
  • @Granitosaurus 只需使用我的示例代码并将WHERE itm.exist(N'LeadDispositionID[.="Lead"] and Jurisdiction[.="NY"]')=1 作为最后一行。尝试使用 and Jurisdiction[.="NY"] 和不使用。尝试使用 and Jurisdiction[.="Blah"]and xyz[.="Blah"] 之类的内容。你不会得到预期的结果...

标签: sql-server xml xpath


【解决方案1】:

您不能简单地将.exist() 中的节点与and 合并。您自己的示例将像这样工作:

SELECT TOP 10 *
FROM @Messages
WHERE PayLoadXml.exist('//VendorLeadItem[LeadDispositionID[.="Lead"] and CampaignOfferTypeID[.="REN"] and Jurisdiction[.="NY"] and MessageId/text()]') = 1

试试这样:

首先声明一个表来模拟您的 Messages 表。插入 3 个案例:

DECLARE @messages TABLE(SomeDescription VARCHAR(100),PayLoadXml XML);
INSERT INTO @messages VALUES
('Your example'
,'<root>
    <Request>
        <RequestData>
            <VendorLeadList>
                <VendorLeadItem>
                    <CampaignOfferTypeID>REN</CampaignOfferTypeID>
                    <LeadDispositionID>Lead</LeadDispositionID>
                    <Jurisdiction>NY</Jurisdiction>
                    <FirstName>Shikasta</FirstName>
                    <LastName>Kashti</LastName>
                    <MessageId>1347_1483825159115_c8273</MessageId>
                </VendorLeadItem>
            </VendorLeadList>
        </RequestData>
        <DualMessageID/>
        <AzureBlobFile/>
        <AzureBlobImageList/>
    </Request>
</root>'
)
,('LeadDispositionID=Slave'
,'<root>
    <Request>
        <RequestData>
            <VendorLeadList>
                <VendorLeadItem>
                    <CampaignOfferTypeID>REN</CampaignOfferTypeID>
                    <LeadDispositionID>Slave</LeadDispositionID>
                    <Jurisdiction>NY</Jurisdiction>
                    <FirstName>Bruno</FirstName>
                    <LastName>Kashti</LastName>
                    <MessageId>1347_1483825159115_c8273</MessageId>
                </VendorLeadItem>
            </VendorLeadList>
        </RequestData>
        <DualMessageID/>
        <AzureBlobFile/>
        <AzureBlobImageList/>
    </Request>
</root>'
)
,('LeadDispositionID=Lead but No MessageId'
,'<root>
    <Request>
        <RequestData>
            <VendorLeadList>
                <VendorLeadItem>
                    <CampaignOfferTypeID>REN</CampaignOfferTypeID>
                    <LeadDispositionID>Lead</LeadDispositionID>
                    <Jurisdiction>NY</Jurisdiction>
                    <FirstName>Bruno</FirstName>
                    <LastName>Kashti</LastName>
                    <MessageId></MessageId>
                </VendorLeadItem>
            </VendorLeadList>
        </RequestData>
        <DualMessageID/>
        <AzureBlobFile/>
        <AzureBlobImageList/>
    </Request>
</root>'
);

这是查询: CROSS APPLY 将确保仅考虑具有 MessageId 的节点。 WHERE 将应用额外的过滤器

SELECT m.*
FROM @messages AS m
CROSS APPLY m.PayLoadXml.nodes(N'/root/Request/RequestData/VendorLeadList/VendorLeadItem[not(empty(MessageId/text()))]') AS A(itm)
WHERE itm.exist(N'LeadDispositionID[text()="Lead"]')=1

如果你需要检查多个条件,你可以使用这个:

WHERE itm.exist(N'.[LeadDispositionID="Slave" and FirstName="Bruno"]')=1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-11
    • 1970-01-01
    • 1970-01-01
    • 2020-12-13
    • 1970-01-01
    • 2015-09-04
    • 2019-03-01
    • 1970-01-01
    相关资源
    最近更新 更多