Столбец запроса XML - получить значение на основе другого значения в той же строке - PullRequest
0 голосов
/ 13 января 2020

в моей базе данных у меня есть XML -колонна, которая выглядит следующим образом:

<Root>
  <Row>
    <Einheit>Stck</Einheit>
    <Faktor>1</Faktor>
    <VkPreisEinheit>1</VkPreisEinheit>
    <VkMengenEinheit>1</VkMengenEinheit>
    <EkMengenEinheit>1</EkMengenEinheit>
    <StcklEinheit>1</StcklEinheit>
    <StcklDefinition>1</StcklDefinition>
    <KonsumentenEinheit>1</KonsumentenEinheit>
  </Row>
  <Row>
    <Einheit>Stück</Einheit>
    <Faktor>100</Faktor>
    <EinheitFaktor>Stck</EinheitFaktor>
    <EkPreisEinheit>1</EkPreisEinheit>
  </Row>
</Root>

Чего я хочу добиться - это получить значение из 'Фактора' только из строки, в которой 'EkPreisEinheit' 'is 1

Я пробовал что-то с:

CASE WHEN isnull(convert(xml,xmlcolumn).value('(/Root/Row/EkPreisEinheit)[1]','nvarchar(max)'),'') = '1'     
     THEN isnull(convert(xml,xmlcolumn).value('(/Root/Row/Faktor)[1]','nvarchar(max)'),'')
     WHEN isnull(convert(xml,xmlcolumn).value('(/Root/Row/EkPreisEinheit)[2]','nvarchar(max)'),'') = '1'
     THEN isnull(convert(xml,xmlcolumn).value('(/Root/Row/Faktor)[2]','nvarchar(max)'),'')
     ELSE ''  
     END AS Faktor

, что сработало бы, если EKPreiseinheit будет найден в обоих столбцах, но только в одном. Также может случиться так, что он будет в первом ряду или в третьем, если он там был. Есть ли способ справиться с этим?

Ответы [ 2 ]

1 голос
/ 13 января 2020

При работе с несколькими одинаковыми узлами вы хотите использовать nodes в FROM, чтобы создать строку для каждого. Это означает, что вы получите что-то вроде этого:

DECLARE @XML xml = '<Root>
  <Row>
    <Einheit>Stck</Einheit>
    <Faktor>1</Faktor>
    <VkPreisEinheit>1</VkPreisEinheit>
    <VkMengenEinheit>1</VkMengenEinheit>
    <EkMengenEinheit>1</EkMengenEinheit>
    <StcklEinheit>1</StcklEinheit>
    <StcklDefinition>1</StcklDefinition>
    <KonsumentenEinheit>1</KonsumentenEinheit>
  </Row>
  <Row>
    <Einheit>Stück</Einheit>
    <Faktor>100</Faktor>
    <EinheitFaktor>Stck</EinheitFaktor>
    <EkPreisEinheit>1</EkPreisEinheit>
  </Row>
</Root>';

WITH YourTable AS(
    SELECT V.YourXML
    FROM (VALUES(@XML)) V(YourXML))
SELECT R.R.value('(EkPreisEinheit/text())[1]','int') AS EkPreisEinheit
FROM YourTable YT
     --Due to the misuse of datatypes you'll need a CONVERT in a VALUES clause here instead
     CROSS APPLY YT.YourXML.nodes('/Root/Row') R(R)
WHERE R.R.value('(EkPreisEinheit/text())[1]','int') IS NOT NULL;
0 голосов
/ 13 января 2020

Вот решение для вас. Несколько моментов для упоминания. (0) Он обрабатывает XML прямо со стола. (1) Он преобразует данные XML в тип данных XML через TRY_CAST(). Таким образом, он будет выдавать NULL, когда XML не будет правильно сформирован без каких-либо ошибок. (2) Он проверяет предикат XPath для элемента <Row>, где значение элемента EkPreisEinheit равно 1, и отфильтровывает все остальное.

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY(1,1) PRIMARY KEY, xmlcolumn NVARCHAR(MAX));
INSERT INTO @tbl
VALUES (N'<Root>
    <Row>
        <Einheit>Stck</Einheit>
        <Faktor>1</Faktor>
        <VkPreisEinheit>1</VkPreisEinheit>
        <VkMengenEinheit>1</VkMengenEinheit>
        <EkMengenEinheit>1</EkMengenEinheit>
        <StcklEinheit>1</StcklEinheit>
        <StcklDefinition>1</StcklDefinition>
        <KonsumentenEinheit>1</KonsumentenEinheit>
    </Row>
    <Row>
        <Einheit>Stück</Einheit>
        <Faktor>100</Faktor>
        <EinheitFaktor>Stck</EinheitFaktor>
        <EkPreisEinheit>1</EkPreisEinheit>
    </Row>
</Root>');
-- DDL and sample data population, end

;WITH rs AS
(
   SELECT ID, TRY_CAST(xmlcolumn AS XML) AS xml_data
   from @tbl
)
SELECT ID
    , col.value('(Faktor/text())[1]','INT') AS Faktor
    , col.value('(EkPreisEinheit/text())[1]','INT') AS EkPreisEinheit
FROM rs as tbl
    CROSS APPLY tbl.xml_data.nodes('/Root/Row[EkPreisEinheit="1"]') AS tab(col);

Выход

+----+--------+----------------+
| ID | Faktor | EkPreisEinheit |
+----+--------+----------------+
|  1 |    100 |              1 |
+----+--------+----------------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...