patternsqlMinor
Using XPath .exist to look for elements within a decimal range
Viewed 0 times
xpathelementsrangedecimallookexistwithinforusing
Problem
I am trying to do a range comparison in an xpath exist - but it is being ignored (returning all rows). The element "caruwmarketfactor" is a decimal value (stored untyped) - can anybody see what I am doing wrong?
The element can appear anywhere in the document - I know in all our cases it will be in there only 1 time. I am looking for the range of .70 to .75.
UPDATE: I just tried using the same logic (value is between a range) for dates and same problem. Whatever I am doing wrong can be applied to dates too.
The element can appear anywhere in the document - I know in all our cases it will be in there only 1 time. I am looking for the range of .70 to .75.
declare @table table (id int identity (1, 1), clientXml xml)
insert into @table (clientXml) values
('
0.7468
'),
('
0.55
'),
('
0.76
')
select id
,clientxml.value('(//*/caruwmarketfactor)[1][text()]', 'decimal (22, 7)')
from @table t
where t.clientXml.exist(N'(//*/caruwmarketfactor[xs:decimal(text()[1]) gt xs:decimal("0.70")])
and (//*/caruwmarketfactor[xs:decimal(text()[1]) lt xs:decimal("0.75")])') = 1UPDATE: I just tried using the same logic (value is between a range) for dates and same problem. Whatever I am doing wrong can be applied to dates too.
Solution
exist return 1 if the expression you use returns at least one node. Put your expression in a query and look at what you get back.select id
,clientxml.value('(//*/caruwmarketfactor)[1][text()]', 'decimal (22, 7)')
,clientXml.query(N'(//*/caruwmarketfactor[xs:decimal(text()[1]) gt xs:decimal("0.70")])
and (//*/caruwmarketfactor[xs:decimal(text()[1]) lt xs:decimal("0.75")])')
from @table tResult:
id
----------- --------------------------------------- ---------
1 0.7468000 true
2 0.5500000 false
3 0.7600000 falseYou get one node back with the value true or false.
You can change your expression to return the value if it matches by doing the logic in the same predicate something like this.
select T.id,
T.clientxml.value('(//*/caruwmarketfactor)[1][text()]', 'decimal (22, 7)')
from @table as T
where T.clientXml.exist('//*/caruwmarketfactor/text()[xs:decimal(.) gt xs:decimal(0.70) and
xs:decimal(.) lt xs:decimal(0.75)]') = 1;The expression within the predicate returns true or false and if it returns true it will return one node to the exist function. If the predicate returns false there will be no node returned.
Logical Expressions (XQuery)
Code Snippets
select id
,clientxml.value('(//*/caruwmarketfactor)[1][text()]', 'decimal (22, 7)')
,clientXml.query(N'(//*/caruwmarketfactor[xs:decimal(text()[1]) gt xs:decimal("0.70")])
and (//*/caruwmarketfactor[xs:decimal(text()[1]) lt xs:decimal("0.75")])')
from @table tid
----------- --------------------------------------- ---------
1 0.7468000 true
2 0.5500000 false
3 0.7600000 falseselect T.id,
T.clientxml.value('(//*/caruwmarketfactor)[1][text()]', 'decimal (22, 7)')
from @table as T
where T.clientXml.exist('//*/caruwmarketfactor/text()[xs:decimal(.) gt xs:decimal(0.70) and
xs:decimal(.) lt xs:decimal(0.75)]') = 1;Context
StackExchange Database Administrators Q#152895, answer score: 4
Revisions (0)
No revisions yet.