2009-05-28 46 views
0

我將描述什麼,我想實現:T-SQL過濾

我傳遞到一個SP的XML與我放到一個表變量名稱值對,比方說@nameValuePairs。 我需要檢索表達式(表)的ID列表與名稱 - 值對(屬性,另一個表)的完全匹配關聯。

這是我的架構:

表達式表 - >(expressionId,屬性Id)

屬性表 - >(屬性Id,的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

正如我在下面指出的,我不相信這個查詢將處理表達式超過匹配屬性的場景。即表達式具有屬性ID(1,2,3,4),所需屬性爲(2,3) – CAbbott 2009-05-29 15:01:04

+0

在您的示例中,此查詢處理表達式具有'至少'(2,3)的情形。在我的情況下,這是可以接受的,但現在你讓我思考。你將如何處理需要精確匹配的場景(必需屬性1,2和表達式1,2,X不返回)? – JohnIdol 2009-05-29 17:15:00

+0

我的查詢應該處理精確匹配(E = {2,3}&A = {2,3});例如過量(E = {2,3,4}&A = {2,3})以及低估(E = {3}&A = {2,3})等情景從最終結果集中排除。 – CAbbott 2009-05-29 17:38:57

回答

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 

編輯:做一些更多的評價後,我發現其中某些詞語將被納入該問題應該不是。我修改了我的查詢,以便將其納入考慮範圍。

1

這不是一個壞的方法,這取決於表的大小和索引,包括@nameValuePairs。如果這些行數很高或者變慢,那麼最好將@namValuePairs放入臨時表中,然後添加適當的索引,並使用單個查詢而不是兩個單獨的查詢。

我注意到,您將列放入#temp中,您沒有使用,排除它們的速度會更快(儘管這將意味着#temp中的重複行)。此外,您的第二個查詢在同一列上同時具有「distinct」和「group by」。你不需要兩者,所以我會放棄「獨特」(可能不會影響性能,因爲優化器已經知道了這一點)。

最後,對於expressionid(我假設這是SQL 2005)上的集羣非唯一索引,#temp可能會更快。您可以在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 
+0

@nameValuePairs有不超過10行(最壞的情況 - 它通常在5-6) – JohnIdol 2009-05-28 21:09:49

1

一我看到的錯誤是你沒有b的別名表,但是你正在使用:a.attributeId = b.attributeId。

嘗試解決這個問題,看看它是否工作,除非我失去了一些東西。

編輯:我認爲你只是解決這個在你的編輯,但它應該是a.attributeId = e.attributeId?