使用 xml 元素 (Tsql) 查询(很多)XML 特定文本的数据
Querying (a lot of) XML data for specific text with in xml Elements (Tsql)
抱歉:post 有点长(想确保所有相关内容都在)
努力让我的大脑围绕这个一点点。
我有一个 table 有 5 列
ID (varchar)
Record value(XML)
date (datetime)
applicationtypeid (int)
applicationstatusid(int)
XML 包含大量数据,但我感兴趣的部分看起来像这样。
<GoodsAndServicesItemSummaryViewModelItems>
<GoodsAndServicesMasterViewModel>
<Id>1</Id>
<ClassId>1</ClassId>
<TermsText>text</TermsText>
<TermsCreationType>ManuallyEntered</TermsCreationType>
<Terms />
特别是 "TermsCreationType" 元素。其中可以是以下3个字符串之一:
- 手动输入
- CopyFromExistingMarks
- 从PreapprovedTermsDatabase复制
根据客户文件的不同,也可能是所有这三种的混合,并且它们可以包含理论上想要的尽可能多的这些混合物,即:
</PriorityClaimAdditionalDetailWizardStepViewModel>
<GoodsAndServicesMasterViewModel>
<Id>9</Id>
<ClassId>2</ClassId>
<TermsText>texty</TermsText>
<TermsCreationType>ManuallyEntered</TermsCreationType>
<Terms />
</GoodsAndServicesMasterViewModel>
<GoodsAndServicesMasterViewModel>
<Id>10</Id>
<ClassId>1</ClassId>
<TermsText>text</TermsText>
<TermsCreationType>ManuallyEntered</TermsCreationType>
<Terms />
</GoodsAndServicesMasterViewModel>
</GoodsAndServicesItemSummaryViewModelItems>
<GoodsAndServicesItemSummaryViewModelItemsUnMerged>
<GoodsAndServicesMasterViewModel>
<Id>9</Id>
<ClassId>9</ClassId>
<TermsText>test</TermsText>
<TermsCreationType>CopyFromExistingMarks</TermsCreationType>
<Terms />
</GoodsAndServicesMasterViewModel>
我正在尝试计算某个日期范围内有多少条记录
仅包含上述之一(无论它出现一次还是出现 50 次,只要它是该元素中的唯一值)
包含三者任意混合的记录。
到目前为止,我对 "one element only" 的尝试是:
SELECT Count (id) [pre-approved only]
FROM [TMWebForms].[dbo].[webformapplication]
WHERE trademarkid NOT IN (SELECT id
FROM [TMWebForms].[dbo].[webformapplication]
WHERE applicationtypeid = '5'
AND createddate BETWEEN '2016-08-01' AND '2016-08-31'
AND RECORDDATA.value('contains((//GoodsAndServicesWizardStepViewModel/GoodsAndServicesItemSummaryViewModelItems/GoodsAndServicesMasterViewModel/TermsCreationType/text())[1], "ManuallyEntered")', 'bit') = 1
AND applicationstatusid = 50
AND applicationtypeid = 5)
AND id NOT IN (SELECT id
FROM [TMWebForms].[dbo].[webformapplication]
WHERE applicationtypeid = '5'
AND createddate BETWEEN '2016-08-01' AND '2016-08-31'
AND RECORDDATA.value('contains((//GoodsAndServicesWizardStepViewModel/GoodsAndServicesItemSummaryViewModelItems/GoodsAndServicesMasterViewModel/TermsCreationType/text())[1], "CopyFromExistingMark")', 'bit') = 1
AND applicationstatusid = 50
AND applicationtypeid = 5)
AND createddate BETWEEN '2016-08-01' AND '2016-08-31'
AND RECORDDATA.value('contains((//GoodsAndServicesWizardStepViewModel/GoodsAndServicesItemSummaryViewModelItems/GoodsAndServicesMasterViewModel/TermsCreationType/text())[1], "CopyFromPreapprovedTermsDatabase")', 'bit') = 1
AND applicationstatusid = 50
AND applicationtypeid = 5
这是长篇大论,从长远来看并不是最好的表现! (我考虑过将其转换为字符串然后使用 "like" - 但这可能同样糟糕,甚至更糟)
它并没有完全拉回我想要的。对我来说,它只搜索 "CopyFromPreapprovedTermsDatabase",但在查询数据时,在少数情况下这是第一行,但我也可以看到 "manuallyentered" 存在。
在此感谢任何帮助!
像这样尝试
(我不得不添加一个 root
并添加一些开始和结束标签)
DECLARE @xml XML=
N'<SomeRoot>
<GoodsAndServicesItemSummaryViewModelItems>
<GoodsAndServicesMasterViewModel>
<Id>9</Id>
<ClassId>2</ClassId>
<TermsText>texty</TermsText>
<TermsCreationType>ManuallyEntered</TermsCreationType>
<Terms />
</GoodsAndServicesMasterViewModel>
<GoodsAndServicesMasterViewModel>
<Id>10</Id>
<ClassId>1</ClassId>
<TermsText>text</TermsText>
<TermsCreationType>ManuallyEntered</TermsCreationType>
<Terms />
</GoodsAndServicesMasterViewModel>
</GoodsAndServicesItemSummaryViewModelItems>
<GoodsAndServicesItemSummaryViewModelItemsUnMerged>
<GoodsAndServicesMasterViewModel>
<Id>9</Id>
<ClassId>9</ClassId>
<TermsText>test</TermsText>
<TermsCreationType>CopyFromExistingMarks</TermsCreationType>
<Terms />
</GoodsAndServicesMasterViewModel>
</GoodsAndServicesItemSummaryViewModelItemsUnMerged>
</SomeRoot>';
DECLARE @tbl TABLE(ID VARCHAR(10),Record_Value XML,[date] DATETIME,applicationtypeid INT,applicationstautsid INT);
INSERT INTO @tbl VALUES('SomeTest',@xml,GETDATE(),11,22);
--CTE 将 select 所有列并添加具有给定 text()
的 TermsCreationType 的实际计数
WITH CTE AS
(
SELECT *
,Record_Value.value('count(//TermsCreationType[text()="ManuallyEntered"])','int') AS CountManuallyEntered
,Record_Value.value('count(//TermsCreationType[text()="CopyFromExistingMarks"])','int') AS CountCopyFromExistingMarks
,Record_Value.value('count(//TermsCreationType[text()="CopyFromPreapprovedTermsDatabase"])','int') AS CountCopyFromPreapprovedTermsDatabase
FROM @tbl
)
--最终的SELECT
使用大的CASE WHEN
层次结构来分析计数
SELECT *
,CASE WHEN CTE.CountManuallyEntered=0 AND CTE.CountCopyFromExistingMarks=0 AND CTE.CountCopyFromPreapprovedTermsDatabase=0 THEN 'None'
ELSE
CASE WHEN CTE.CountManuallyEntered>0 AND CTE.CountCopyFromExistingMarks=0 AND CTE.CountCopyFromPreapprovedTermsDatabase=0 THEN 'Manually'
ELSE
CASE WHEN CTE.CountManuallyEntered=0 AND CTE.CountCopyFromExistingMarks>0 AND CTE.CountCopyFromPreapprovedTermsDatabase=0 THEN 'Existing'
ELSE
CASE WHEN CTE.CountManuallyEntered=0 AND CTE.CountCopyFromExistingMarks=0 AND CTE.CountCopyFromPreapprovedTermsDatabase>0 THEN 'Preapproved'
ELSE
'Mixed'
END
END
END
END AS CountAnalysis
FROM CTE;
抱歉:post 有点长(想确保所有相关内容都在)
努力让我的大脑围绕这个一点点。 我有一个 table 有 5 列
ID (varchar)
Record value(XML)
date (datetime)
applicationtypeid (int)
applicationstatusid(int)
XML 包含大量数据,但我感兴趣的部分看起来像这样。
<GoodsAndServicesItemSummaryViewModelItems>
<GoodsAndServicesMasterViewModel>
<Id>1</Id>
<ClassId>1</ClassId>
<TermsText>text</TermsText>
<TermsCreationType>ManuallyEntered</TermsCreationType>
<Terms />
特别是 "TermsCreationType" 元素。其中可以是以下3个字符串之一:
- 手动输入
- CopyFromExistingMarks
- 从PreapprovedTermsDatabase复制
根据客户文件的不同,也可能是所有这三种的混合,并且它们可以包含理论上想要的尽可能多的这些混合物,即:
</PriorityClaimAdditionalDetailWizardStepViewModel>
<GoodsAndServicesMasterViewModel>
<Id>9</Id>
<ClassId>2</ClassId>
<TermsText>texty</TermsText>
<TermsCreationType>ManuallyEntered</TermsCreationType>
<Terms />
</GoodsAndServicesMasterViewModel>
<GoodsAndServicesMasterViewModel>
<Id>10</Id>
<ClassId>1</ClassId>
<TermsText>text</TermsText>
<TermsCreationType>ManuallyEntered</TermsCreationType>
<Terms />
</GoodsAndServicesMasterViewModel>
</GoodsAndServicesItemSummaryViewModelItems>
<GoodsAndServicesItemSummaryViewModelItemsUnMerged>
<GoodsAndServicesMasterViewModel>
<Id>9</Id>
<ClassId>9</ClassId>
<TermsText>test</TermsText>
<TermsCreationType>CopyFromExistingMarks</TermsCreationType>
<Terms />
</GoodsAndServicesMasterViewModel>
我正在尝试计算某个日期范围内有多少条记录
仅包含上述之一(无论它出现一次还是出现 50 次,只要它是该元素中的唯一值)
包含三者任意混合的记录。
到目前为止,我对 "one element only" 的尝试是:
SELECT Count (id) [pre-approved only]
FROM [TMWebForms].[dbo].[webformapplication]
WHERE trademarkid NOT IN (SELECT id
FROM [TMWebForms].[dbo].[webformapplication]
WHERE applicationtypeid = '5'
AND createddate BETWEEN '2016-08-01' AND '2016-08-31'
AND RECORDDATA.value('contains((//GoodsAndServicesWizardStepViewModel/GoodsAndServicesItemSummaryViewModelItems/GoodsAndServicesMasterViewModel/TermsCreationType/text())[1], "ManuallyEntered")', 'bit') = 1
AND applicationstatusid = 50
AND applicationtypeid = 5)
AND id NOT IN (SELECT id
FROM [TMWebForms].[dbo].[webformapplication]
WHERE applicationtypeid = '5'
AND createddate BETWEEN '2016-08-01' AND '2016-08-31'
AND RECORDDATA.value('contains((//GoodsAndServicesWizardStepViewModel/GoodsAndServicesItemSummaryViewModelItems/GoodsAndServicesMasterViewModel/TermsCreationType/text())[1], "CopyFromExistingMark")', 'bit') = 1
AND applicationstatusid = 50
AND applicationtypeid = 5)
AND createddate BETWEEN '2016-08-01' AND '2016-08-31'
AND RECORDDATA.value('contains((//GoodsAndServicesWizardStepViewModel/GoodsAndServicesItemSummaryViewModelItems/GoodsAndServicesMasterViewModel/TermsCreationType/text())[1], "CopyFromPreapprovedTermsDatabase")', 'bit') = 1
AND applicationstatusid = 50
AND applicationtypeid = 5
这是长篇大论,从长远来看并不是最好的表现! (我考虑过将其转换为字符串然后使用 "like" - 但这可能同样糟糕,甚至更糟)
它并没有完全拉回我想要的。对我来说,它只搜索 "CopyFromPreapprovedTermsDatabase",但在查询数据时,在少数情况下这是第一行,但我也可以看到 "manuallyentered" 存在。
在此感谢任何帮助!
像这样尝试
(我不得不添加一个 root
并添加一些开始和结束标签)
DECLARE @xml XML=
N'<SomeRoot>
<GoodsAndServicesItemSummaryViewModelItems>
<GoodsAndServicesMasterViewModel>
<Id>9</Id>
<ClassId>2</ClassId>
<TermsText>texty</TermsText>
<TermsCreationType>ManuallyEntered</TermsCreationType>
<Terms />
</GoodsAndServicesMasterViewModel>
<GoodsAndServicesMasterViewModel>
<Id>10</Id>
<ClassId>1</ClassId>
<TermsText>text</TermsText>
<TermsCreationType>ManuallyEntered</TermsCreationType>
<Terms />
</GoodsAndServicesMasterViewModel>
</GoodsAndServicesItemSummaryViewModelItems>
<GoodsAndServicesItemSummaryViewModelItemsUnMerged>
<GoodsAndServicesMasterViewModel>
<Id>9</Id>
<ClassId>9</ClassId>
<TermsText>test</TermsText>
<TermsCreationType>CopyFromExistingMarks</TermsCreationType>
<Terms />
</GoodsAndServicesMasterViewModel>
</GoodsAndServicesItemSummaryViewModelItemsUnMerged>
</SomeRoot>';
DECLARE @tbl TABLE(ID VARCHAR(10),Record_Value XML,[date] DATETIME,applicationtypeid INT,applicationstautsid INT);
INSERT INTO @tbl VALUES('SomeTest',@xml,GETDATE(),11,22);
--CTE 将 select 所有列并添加具有给定 text()
WITH CTE AS
(
SELECT *
,Record_Value.value('count(//TermsCreationType[text()="ManuallyEntered"])','int') AS CountManuallyEntered
,Record_Value.value('count(//TermsCreationType[text()="CopyFromExistingMarks"])','int') AS CountCopyFromExistingMarks
,Record_Value.value('count(//TermsCreationType[text()="CopyFromPreapprovedTermsDatabase"])','int') AS CountCopyFromPreapprovedTermsDatabase
FROM @tbl
)
--最终的SELECT
使用大的CASE WHEN
层次结构来分析计数
SELECT *
,CASE WHEN CTE.CountManuallyEntered=0 AND CTE.CountCopyFromExistingMarks=0 AND CTE.CountCopyFromPreapprovedTermsDatabase=0 THEN 'None'
ELSE
CASE WHEN CTE.CountManuallyEntered>0 AND CTE.CountCopyFromExistingMarks=0 AND CTE.CountCopyFromPreapprovedTermsDatabase=0 THEN 'Manually'
ELSE
CASE WHEN CTE.CountManuallyEntered=0 AND CTE.CountCopyFromExistingMarks>0 AND CTE.CountCopyFromPreapprovedTermsDatabase=0 THEN 'Existing'
ELSE
CASE WHEN CTE.CountManuallyEntered=0 AND CTE.CountCopyFromExistingMarks=0 AND CTE.CountCopyFromPreapprovedTermsDatabase>0 THEN 'Preapproved'
ELSE
'Mixed'
END
END
END
END AS CountAnalysis
FROM CTE;