我将描述我想要实现的目标:
我传递给一个带有名称值对的SP xml,我把它放到一个表变量中,比方说@nameValuePairs
。
我需要检索表达式(表)的ID列表,其中包含与名称 - 值对(属性,另一个表)相关联的精确匹配。
这是我的架构:
表达式表 - > (expressionId,attributeId)
属性表 - > (attributeId,attributeName,attributeValue)
使用动态SQL和邪恶游标尝试复杂的东西(虽然有效,但速度很慢),这就是我现在所拥有的:
--do the magic plz!
-- retrieve number of name-value pairs
SET @noOfAttributes = select count(*) from @nameValuePairs
select distinct
e.expressionId, a.attributeName, a.attributeValue
into
#temp
from
expressions e
join
attributes a
on
e.attributeId = a.attributeId
join --> this join does the filtering
@nameValuePairs nvp
on
a.attributeName = nvp.name and a.attributeValue = nvp.value
group by
e.expressionId, a.attributeName, a.attributeValue
-- now select the IDs I need
-- since I did a select distinct above if the number of matches
-- for a given ID is the same as noOfAttributes then BINGO!
select distinct
expressionId
from
#temp
group by expressionId
having count(*) = @noOfAttributes
请人们查看并查看他们是否能发现任何问题?有没有更好的方法呢?
任何帮助表示赞赏!
答案 0 :(得分:1)
这不是一个糟糕的方法,具体取决于表的大小和索引,包括@nameValuePairs。如果这些行数很高或者变得很慢,你可能最好将@namValuePairs放入临时表中,添加适当的索引,并使用单个查询而不是两个单独的查询。
我注意到你将列放入你未使用的#temp中,排除它们会更快(尽管它会意味着#temp中的重复行)。此外,您的第二个查询在同一列上同时具有“distinct”和“group by”。你不需要两者,所以我会删除“distinct”(可能不会影响性能,因为优化器已经想到了这一点)。
最后,对于expressionid上的聚簇非唯一索引,#temp可能会更快(我假设这是SQL 2005)。您可以在SELECT..INTO之后添加它,但在加载之前添加它通常会更快或更快。这将要求您首先创建#temp,添加集群,然后使用INSERT..SELECT来加载它。
我将添加一个合并查询的示例...好吧,这是将它们合并为单个查询的一种方法(这也应该是2000兼容的):
-- retrieve number of name-value pairs
SET @noOfAttributes = select count(*) from @nameValuePairs
-- now select the IDs I need
-- since I did a select distinct above if the number of matches
-- for a given ID is the same as noOfAttributes then BINGO!
select
expressionId
from
(
select distinct
e.expressionId, a.attributeName, a.attributeValue
from
expressions e
join
attributes a
on
e.attributeId = a.attributeId
join --> this join does the filtering
@nameValuePairs nvp
on
a.attributeName = nvp.name and a.attributeValue = nvp.value
) as Temp
group by expressionId
having count(*) = @noOfAttributes
答案 1 :(得分:1)
我看到的一个错误是你没有别名为b的表,但你正在使用:a.attributeId = b.attributeId。
尝试修复它,看它是否有效,除非我遗漏了什么。
编辑:我认为你刚刚在你的编辑中解决了这个问题,但它应该是a.attributeId = e.attributeId吗?答案 2 :(得分:1)
我相信这会满足你想要满足的要求。我不确定它有多漂亮,但它应该有效并且不需要临时表:
SET @noOfAttributes = select count(*) from @nameValuePairs
SELECT e.expressionid
FROM expression e
LEFT JOIN (
SELECT attributeid
FROM attributes a
JOIN @nameValuePairs nvp ON nvp.name = a.Name AND nvp.Value = a.value
) t ON t.attributeid = e.attributeid
GROUP BY e.expressionid
HAVING SUM(CASE WHEN t.attributeid IS NULL THEN (@noOfAttributes + 1) ELSE 1 END) = @noOfAttributes
编辑:在做了一些更多的评估后,我发现了一个问题,其中包含了不应该包含的某些表达式。我已经修改了我的查询以将其纳入帐户。