Sql server 在SQL中的xml列中搜索多个值
这是我的桌子Sql server 在SQL中的xml列中搜索多个值,sql-server,xml,sql-server-2008,xquery-sql,Sql Server,Xml,Sql Server 2008,Xquery Sql,这是我的桌子 BasketId(int) BasketName(varchar) BasketFruits(xml) 1 Gold <FRUITS><FID>1</FID><FID>2</FID><FID>3</FID><FID>4</FID><FID>5</FID><FID>6</FID></FRUITS
BasketId(int) BasketName(varchar) BasketFruits(xml)
1 Gold <FRUITS><FID>1</FID><FID>2</FID><FID>3</FID><FID>4</FID><FID>5</FID><FID>6</FID></FRUITS>
2 Silver <FRUITS><FID>1</FID><FID>2</FID><FID>3</FID><FID>4</FID></FRUITS>
3 Bronze <FRUITS><FID>3</FID><FID>4</FID><FID>5</FID></FRUITS>
如果是T-SQL,我会像这样使用IN子句
SELECT * FROM Baskets where FID in (1,3)
感谢您的帮助/解决方案……这是否太琐碎了
SELECT * FROM Baskets WHERE BasketFruits LIKE '%<FID>1</FID>%' AND BasketFruits LIKE '%<FID>3</FID>%'
这比我希望的要复杂一点,但这个解决方案是有效的 基本上,我使用的是一个CTE公共表表达式,它分解表并交叉连接从节点到篮名的所有值 从该CTE中,我选择那些同时包含值1和3的篮子
第一种选择是在where子句中添加另一个exist
declare @fruitId1 int;
set @fruitId1=1;
declare @fruitId2 int;
set @fruitId2=3;
select *
from @Test
where
BasketFruits.exist('/FRUITS/FID[.=sql:variable("@fruitId1")]')=1 and
BasketFruits.exist('/FRUITS/FID[.=sql:variable("@fruitId2")]')=1
另一个版本是在xquery语句中使用这两个变量,计算命中率
select *
from @Test
where BasketFruits.value(
'count(distinct-values(/FRUITS/FID[.=(sql:variable("@fruitId1"),sql:variable("@fruitId2"))]))', 'int') = 2
如果您知道在编写查询时要使用多少FID参数,那么上面的两个查询就可以正常工作。如果您的FID数量不同,您可以使用类似的方法
declare @FIDs xml = '<FID>1</FID><FID>3</FID>'
;with cteParam(FID) as
(
select T.N.value('.', 'int')
from @FIDs.nodes('FID') as T(N)
)
select T.BasketName
from @Test as T
cross apply T.BasketFruits.nodes('/FRUITS/FID') as F(FID)
inner join cteParam as p
on F.FID.value('.', 'int') = P.FID
group by T.BasketName
having count(T.BasketName) = (select count(*) from cteParam)
将@FIDs变量构建为XML,以保存要在查询中使用的值
您可以在此处测试最后一个查询:此解决方案毫无疑问有效。干得好!但是,如果匹配的值的数量像现在这样增加,如果我想搜索具有果ID 1、2和3的篮子,则必须使用动态查询连接另一个EXISTS语句。或者我想,我需要在while循环中递归调用这个存储过程…?@nav:是的,我同意-解决方案并不完美,因为它不可扩展-但我现在想不出任何其他方法-非常好的工作!!我一直在寻找这个答案。伟大的工作米凯尔·埃里克森。你就是那个人!
declare @fruitId1 int;
set @fruitId1=1;
declare @fruitId2 int;
set @fruitId2=3;
select *
from @Test
where
BasketFruits.exist('/FRUITS/FID[.=sql:variable("@fruitId1")]')=1 and
BasketFruits.exist('/FRUITS/FID[.=sql:variable("@fruitId2")]')=1
select *
from @Test
where BasketFruits.value(
'count(distinct-values(/FRUITS/FID[.=(sql:variable("@fruitId1"),sql:variable("@fruitId2"))]))', 'int') = 2
declare @FIDs xml = '<FID>1</FID><FID>3</FID>'
;with cteParam(FID) as
(
select T.N.value('.', 'int')
from @FIDs.nodes('FID') as T(N)
)
select T.BasketName
from @Test as T
cross apply T.BasketFruits.nodes('/FRUITS/FID') as F(FID)
inner join cteParam as p
on F.FID.value('.', 'int') = P.FID
group by T.BasketName
having count(T.BasketName) = (select count(*) from cteParam)