Я не знаю, что "XML будет полностью динамичным" действительно означает. Как видно, всегда будет <Root>
и множество <row>
элементов. Таким образом, динамическая часть - это неизвестный список полей в каждом <row>
. Правильно?
Вы можете попробовать кое-что по этому поводу:
DECLARE @tbl1 TABLE(XMLValue XML);
INSERT INTO @tbl1
VALUES
(
'<Root>
<row>
<VendorPlantName>Plant 1</VendorPlantName>
<TotalAttainableUnits>3693</TotalAttainableUnits>
</row>
<row>
<VendorPlantName>Plant 2</VendorPlantName>
<TotalAttainableUnits>69477</TotalAttainableUnits>
</row>
<row>
<VendorPlantName>Plant 3</VendorPlantName>
<TotalAttainableUnits>573</TotalAttainableUnits>
</row>
</Root>'
);
DECLARE @tbl2 TABLE(NodeName NVARCHAR(255)
,NodeValue NVARCHAR(255)
);
INSERT INTO @tbl2
VALUES
(
'VendorPlantName','Plant 2'
),
(
'VendorPlantName','Plant 1'
);
- Cte создает список исключений
WITH ExcludeFields(ExclFld) AS
(
SELECT NodeName AS [@nn]
,NodeValue AS [@nv]
FROM @tbl2 t2
FOR XML PATH('exclFld'),TYPE
)
SELECT Combined.query('
<Root>
{
for $rw in /row
return
<row>
{
for $fld in $rw/*
return
if(/exclFld[@nn=local-name($fld)]/@nv=$fld/text()) then
<x/>
else
$fld
}
</row>
}
</Root>
')
.query('/Root/row[empty(x)]')
FROM ExcludeFields ef
CROSS JOIN @tbl1 t1
CROSS APPLY(SELECT ef.ExclFld AS [*]
,t1.XMLValue.query('/Root/row')
FOR XML PATH(''),TYPE) A(Combined);
Идея вshort:
Мы создаем промежуточный XML, содержащий ваши строки и список исключаемых полей:
<exclFld nn="VendorPlantName" nv="Plant 2" />
<exclFld nn="VendorPlantName" nv="Plant 1" />
<row>
<VendorPlantName>Plant 1</VendorPlantName>
<TotalAttainableUnits>3693</TotalAttainableUnits>
</row>
<row>
<VendorPlantName>Plant 2</VendorPlantName>
<TotalAttainableUnits>69477</TotalAttainableUnits>
</row>
<row>
<VendorPlantName>Plant 3</VendorPlantName>
<TotalAttainableUnits>573</TotalAttainableUnits>
</row>
Нет, мы не можем использовать подход XQuery-FLWOR, чтобы проходить через каждую строку, а затем через каждуюполе и возвращает <x/>
, если комбинация имени узла и значения узла существует в списке исключаемых полей.
С помощью этого XML мы можем запустить другой XQuery, получая только строки, в которых нет <x>
.
Другой подход
... Вы можете уничтожить это и использовать стандартный SQL для тяжелой работы:
WITH TheRows AS
(
SELECT ROW_NUMBER() OVER(ORDER BY A.rw) AS RowNumber
,rw.query('.') TheRow
FROM @tbl1 t1
CROSS APPLY t1.XMLValue.nodes('/Root/row') A(rw)
)
,EAV AS
(
SELECT r.RowNumber
,fld.value('local-name(.)','nvarchar(1000)') AS FieldName
,fld.value('text()[1]','nvarchar(1000)') AS FieldValue
FROM TheRows r
CROSS APPLY r.TheRow.nodes('row/*') Each(fld)
)
,SkipRows AS
(
SELECT EAV.RowNumber
FROM EAV
WHERE EXISTS(SELECT 1 FROM @tbl2 t2 WHERE t2.NodeName=EAV.FieldName AND t2.NodeValue=EAV.FieldValue)
GROUP BY EAV.RowNumber
)
SELECT *
FROM EAV
WHERE EAV.RowNumber NOT IN (SELECT sr.RowNumber FROM SkipRows sr);
Последний результатможет быть легко возвращено как XML - при необходимости.