views:

19

answers:

1

I am trying to select from SQL Server 2005 XML datatype some values based on the max data that is located in a child node.

I have multiple rows with XML similar to the following stored in a field in SQL Server:

<user>
   <name>Joe</name>
      <token>
         <id>ABC123</id>
         <endDate>2013-06-16 18:48:50.111</endDate>
      </token>
      <token>
         <id>XYX456</id>
         <endDate>2014-01-01 18:48:50.111</endDate>
      </token>
</user>

I want to perform a select from this XML column where it determines the max date within the token element and would return the datarows similar to the result below for each record:

Joe XYZ456 2014-01-01 18:48:50.111

I have tried to find a max function for xpath that would all me to select the correct token element but I couldn't find one that would work.

I also tried to use the SQL MAX function but I wasn't able to get it working with that method either.

If I only have a single token it of course works fine but when I have more than one I get a NULL, most likely because the query doesn't know which date to pull. I was hoping there would be a way to specify a where clause [max(endDate)] on the token element but haven't found a way to do that.

Here is an example of the one that works when I only have a single token:

SELECT 
XMLCOL.query('user/name').value('.','NVARCHAR(20)') as name
XMLCOL.query('user/token/id').value('.','NVARCHAR(20)') as id
XMLCOL.query('user/token/endDate').value(,'xs:datetime(.)','DATETIME') as endDate
FROM MYTABLE
A: 

How about this:

SELECT 
    TOP 1
    XMLCOL.value('(/user/name)[1]', 'nvarchar(20)') as 'UserName',
    Usr.Token.value('(id)[1]', 'nvarchar(20)') AS 'ID',
    Usr.Token.value('(endDate)[1]', 'DateTime') as 'EndDate'
FROM 
    dbo.MyTable
CROSS APPLY
    xmlcol.nodes('/user/token') AS Usr(Token)
ORDER BY
    Usr.Token.value('(endDate)[1]', 'DateTime') DESC

You basically take the "atomic" part like 'UserName' directly from the XML, and then cross apply a list of /user/token and extract the individual bits you want - you get a result set of three columns (UserName, ID, EndDate) and you can order and filter those.

Side note: instead of this:

XMLCOL.query('user/name').value('.','NVARCHAR(20)') 

why don't you use this - feels much easier!

XMLCOL.value('(/user/name)[1]', 'NVARCHAR(20)') 
marc_s
The CROSS APPLY did the trick. It wasn't exactly what I needed but you pointed me in the right direction. Thanks.
Jay