Более эффективный способ синтаксического анализа XML - PullRequest
1 голос
/ 11 июля 2020

Ниже приведен пример задачи, над которой я работаю, и я хотел бы знать, есть ли способ выполнить указанные ниже операции за один проход вместо трех. Я извлекаю данные дочернего узла из 3 узлов документа, а затем объединяю их в одну запись на основе «имени поля». Запрос ниже является эффективным, однако мне было бы любопытно, есть ли способ выполнить обработку данных за один проход вместо 3?

DECLARE @T TABLE(MenuID INT, DefaultListView NVARCHAR(MAX)) -- <-- This is this way in the DB
INSERT @T VALUES
(1,
'<ListPageUserPreference xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <SelectFields>
        <ListPageUPSelectField>
            <FieldName>AbstractPreparedBy</FieldName>
            <DisplayIndex>14</DisplayIndex>
            <FieldWidth>112</FieldWidth>
        </ListPageUPSelectField>
        <ListPageUPSelectField>
            <FieldName>AccountingType</FieldName>
            <DisplayIndex>3</DisplayIndex>
            <FieldWidth>112</FieldWidth>
        </ListPageUPSelectField>
        <ListPageUPSelectField>
            <FieldName>BuildingAddress_1</FieldName>
            <DisplayIndex>4</DisplayIndex>
            <FieldWidth>112</FieldWidth>
        </ListPageUPSelectField>
        <ListPageUPSelectField>
            <FieldName>BuildingName</FieldName>
            <DisplayIndex>0</DisplayIndex>
            <FieldWidth>112</FieldWidth>
        </ListPageUPSelectField>
        <ListPageUPSelectField>
            <FieldName>BuildingCity</FieldName>
            <DisplayIndex>5</DisplayIndex>
            <FieldWidth>112</FieldWidth>
        </ListPageUPSelectField>
        <ListPageUPSelectField>
            <FieldName>BuildingCountry</FieldName>
            <DisplayIndex>2</DisplayIndex>
            <FieldWidth>112</FieldWidth>
        </ListPageUPSelectField>
        <ListPageUPSelectField>
            <FieldName>EndDate</FieldName>
            <DisplayIndex>8</DisplayIndex>
            <FieldWidth>112</FieldWidth>
        </ListPageUPSelectField>
    </SelectFields>
    <GroupByFields>
        <ListPageUPGroupByColumn>
            <GroupByIndex>0</GroupByIndex>
            <GroupByField>BuildingCountry</GroupByField>
        </ListPageUPGroupByColumn>
    </GroupByFields>
    <SortByFields>
        <ListPageUPSortByColumn>
            <SortByIndex>0</SortByIndex>
            <SortByField>BuildingCountry</SortByField>
            <SortDirection>Descending</SortDirection>
        </ListPageUPSortByColumn>
    </SortByFields>
    <PageSize>50</PageSize>
    <FilterOption>0</FilterOption>
    <Filter>[LeaseActive] = True</Filter>
    <distinct/>
    <ArchiveActive>1</ArchiveActive>
    <ExpandAll>false</ExpandAll>
</ListPageUserPreference>')



;WITH XmlData AS 
(
    SELECT 
        MenuID, 
        XmlNodes = CAST(DefaultListView AS XML)
    FROM 
        @T
)
,GridLevelData AS
(
    SELECT
        MenuID,
        PageSize = ISNULL(XmlNodes.value('(/ListPageUserPreference/PageSize)[1]', 'INT'), 25),
        FilterOption = ISNULL(XmlNodes.value('(/ListPageUserPreference/FilterOption)[1]', 'INT'),0),
        Filter = XmlNodes.value('(/ListPageUserPreference/Filter)[1]', 'NVARCHAR(MAX)'),
        ArchiveActive = ISNULL(XmlNodes.value('(/ListPageUserPreference/ArchiveActive)[1]', 'INT'),0),--!!!
        ExpandAll = ISNULL(XmlNodes.value('(/ListPageUserPreference/ExpandAll)[1]', 'BIT'),0),---!!!
        IsDistinct = ISNULL(XmlNodes.exist('(/ListPageUserPreference/distinct)[1]'),0)---!!!
    FROM
        XmlData
)
,SelectedFields AS
(
    SELECT
        MenuID,
        FieldName = Fields.Field.value('(FieldName)[1]', 'VARCHAR(150)'),
        DisplayIndex = Fields.Field.value('(DisplayIndex)[1]', 'INT'),
        FieldWidth = Fields.Field.value('(FieldWidth)[1]', 'INT')
    FROM
        XmlData
        CROSS APPLY XmlNodes.nodes('/ListPageUserPreference/SelectFields/ListPageUPSelectField') AS Fields(Field)

)
,GroupingFields AS
(
    SELECT
        MenuID,
        FieldName = Fields.Field.value('(GroupByField)[1]', 'VARCHAR(150)'),
        GroupByIndex = Fields.Field.value('(GroupByIndex)[1]', 'INT')
    FROM
        XmlData
        CROSS APPLY XmlNodes.nodes('/ListPageUserPreference/GroupByFields/ListPageUPGroupByColumn') AS Fields(Field)
)
,SortingFields AS
(
    SELECT
        MenuID,
        FieldName = Fields.Field.value('(SortByField)[1]', 'NVARCHAR(50)'),
        SortByIndex = Fields.Field.value('(SortByIndex)[1]', 'INT'),
        SortDirection =  Fields.Field.value('(SortDirection)[1]', 'NVARCHAR(50)')
    FROM
        XmlData
        CROSS APPLY XmlNodes.nodes('/ListPageUserPreference/SortByFields/ListPageUPSortByColumn') AS Fields(Field)
)
,FieldsCombinedAndNormalized AS
(
    SELECT
        SF.MenuID,
        SF.FieldName,
        visibleIndex = SF.DisplayIndex,
        FieldWidth = CASE WHEN ISNULL(SF.FieldWidth,0) = 0 THEN 100 ELSE SF.FieldWidth END, --!!!
        IsGrouped = CASE WHEN GF.MenuID IS NULL THEN 0 ELSE 1 END,
        GroupByIndex = ISNULL(GF.GroupByIndex,0),
        IsSorted = CASE WHEN SR.MenuID IS NULL THEN 0 ELSE 1 END,
        SortByIndex = ISNULL(SR.SortByIndex,0),
        SortDirection = SR.SortDirection,
        DisplayIndex
    FROM
        SelectedFields SF
        LEFT OUTER JOIN GroupingFields GF ON GF.MenuID = SF.MenuID AND GF.FieldName = SF.FieldName 
        LEFT OUTER JOIN SortingFields SR ON SR.MenuID = SF.MenuID AND SR.FieldName = SF.FieldName 
)

SELECT * FROM FieldsCombinedAndNormalized
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...