Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vue.js/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 在SQL中的xml列中搜索多个值_Sql Server_Xml_Sql Server 2008_Xquery Sql - Fatal编程技术网

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)