0

In SQL Server 2014 a table with a CustomColumns column that contains XML data with the following structure:

<CustomColumnsCollection>
  <CustomColumn>
    <Name>Brand</Name>
    <DataType>0</DataType>
    <Value>Duprim</Value>
  </CustomColumn>
  <CustomColumn>
    <Name>LabelGroup</Name>
    <DataType>0</DataType>
    <Value />
  </CustomColumn>
...
</CustomColumnsCollection>

I want to get value of column Value where column Name equals, i.e. 'Brand' (the following code is a part of bigger query, which I saved as VIEW):

MAX(DISTINCT PR.CustomColumns.value('(/CustomColumnsCollection/CustomColumn/Name="Brand"/Value)[0]', 'varchar(max)')) AS Brand

In this case I would like it to return 'Duprim'. How is this achieved?

2 Answers 2

2

Here is another method by using XPath predicate.

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, CustomColumns XML);
INSERT INTO @tbl (CustomColumns)
VALUES
(N'<CustomColumnsCollection>
    <CustomColumn>
        <Name>Brand</Name>
        <DataType>0</DataType>
        <Value>Duprim</Value>
    </CustomColumn>
    <CustomColumn>
        <Name>LabelGroup</Name>
        <DataType>0</DataType>
        <Value/>
    </CustomColumn>
</CustomColumnsCollection>');
-- DDL and sample data population, end

DECLARE @param VARCHAR(30) = 'Brand';

SELECT  ID
    , c.value('(Value/text())[1]', 'VARCHAR(50)') AS [Value]
FROM @tbl
    CROSS APPLY CustomColumns.nodes('/CustomColumnsCollection/CustomColumn[(Name/text())[1] eq sql:variable("@param")]') AS t(c);

-- hard-coded value
SELECT  ID
    , c.value('(Value/text())[1]', 'VARCHAR(50)') AS [Value]
FROM @tbl
    CROSS APPLY CustomColumns.nodes('/CustomColumnsCollection/CustomColumn[(Name/text())[1] eq "Brand"]') AS t(c);

Output

+----+--------+
| ID | Value  |
+----+--------+
|  1 | Duprim |
+----+--------+

To help you with the view that is consumed by the MS Excel. It would be great if you could provide a minimal reproducible example: (1) DDL and sample data population, i.e. CREATE table(s) plus INSERT, T-SQL statements. (2) What you need to do, i.e. logic. (3) Desired output based on the sample data in #1 above.

SQL for Excel

SELECT ID
    , CustomColumns.value('(/CustomColumnsCollection/CustomColumn[(Name/text())[1] eq "Brand"]/Value/text())[1]', 'VARCHAR(50)') AS [Value]
FROM @tbl;
Sign up to request clarification or add additional context in comments.

5 Comments

thanks for the answer, but in this instance I'm using views and cannot declare variables, as far as I know...
@Elen. In such case you can use just a hard-coded value. I updated the answer.
thanks @Yizhak, perhaps I can just use Excel to parse it then, not sure how to hard code it
I see what you did there. That would work for me, however when I applied it to my query as MAX(DISTINCT PR.CustomColumns.nodes('/CustomColumnsCollection/CustomColumn[(Name/text())[1] eq "Brand"]')) AS Spec0, SQL server gives me error nodes is not valid function... sorry I'm new to parsing XML within sql queries....
@Elen, if allowed you might switch from the VIEW to an inline function. Such a function will accept your input as parameter and will allow for the code in this answer using sql:variable(). Within Excel you can pass the needed value into the function easily.
0

Try something like this:

SELECT
    xc.value('(Value)[1]', 'varchar(50)') 
FROM
    PR
CROSS APPLY
    PR.CustomColumns.nodes('/CustomColumnsCollection/CustomColumn') AS XT(XC)
WHERE   
    xc.value('(Name)[1]', 'varchar(50)') = 'Brand'

The .nodes() returns a list of XML fragments, each representing a <CustomColumn> node. Select the one with the Name value of Brand in the WHERE clause, and get the value of Value for that XML node

1 Comment

I ran this as subquery with FROM dbo.Products as PR, but it returned nothing....

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.