0

我将描述我想要实现的目标:

我将一个带有名称值对的 xml 传递给 SP,我将其放入表变量中,比如说@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 

人们可以请检查一下,看看他们是否能发现任何问题?有没有更好的方法来做到这一点?

任何帮助表示赞赏!

4

3 回答 3

1

这不是一个坏方法,具体取决于表的大小和索引,包括@nameValuePairs。如果这些行数很高或者变得很慢,则最好将 @namValuePairs 放入临时表中,添加适当的索引,并使用单个查询而不是两个单独的查询。

我确实注意到您将不使用的列放入#temp,排除它们会更快(尽管这意味着#temp 中的重复行)。此外,您的第二个查询在同一列上同时具有“不同”和“分组依据”。你不需要两者,所以我会放弃“不同的”(可能不会影响性能,因为优化器已经解决了这个问题)。

最后,#temp 使用 expressionid 上的聚集非唯一索引可能会更快(我假设这是 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
于 2009-05-28T21:07:08.903 回答
1

我看到的一个错误是您没有别名为 b 的表,但您正在使用:a.attributeId = b.attributeId。

尝试修复它,看看它是否有效,除非我遗漏了什么。

编辑:我认为您刚刚在编辑中修复了这个问题,但它应该是 a.attributeId = e.attributeId 吗?

于 2009-05-28T21:08:24.470 回答
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

编辑:在进行了更多评估之后,我发现了一个问题,其中包含某些不应该包含的表达式。我已经修改了我的查询以考虑到这一点。

于 2009-05-28T21:43:40.873 回答