2010-07-23 88 views
0

我想知道別人怎麼處理這樣的場景:從多選標準構建查詢

說我有多種選擇供用戶選擇。

一樣,顏色,尺寸,品牌,型號等

什麼是最好的解決方案或做法來處理您的查詢的構建這個scneario?

因此,如果他們選擇8種可能顏色中的6種,可能的7種中的4種,以及12種可能的品牌中的8種?

你可以做動態OR語句或動態IN語句,但我想弄清楚是否有更好的解決方案來處理這個「WHERE」條件類型邏輯?

編輯: 我得到了一些非常好的反饋(謝謝大家)...另外一件事要注意的是,一些選擇甚至可能是像(40可能46選擇)如此種類大。再次感謝!

感謝,

小號

回答

0

什麼是處理此場景的查詢構建的最佳解決方案或實踐?

動態SQL。

單個參數表示兩種狀態 - NULL /不存在或具有值。另外兩種方法意味着對參數個數進行平方以得到總可能性的數量:2得到4,3得出9等等。一個單一的非動態查詢可以包含所有可能性,但是在使用以下內容之間可能會出現可怕的表現:

  1. 手術室
  2. 整體非sargability
  3. 並不能重複使用查詢計劃

...時相比,構造查詢出來的只有絕對必要的部分動態SQL查詢。

如果您使用sp_executesql命令,則查詢計劃會緩存在SQL Server 2005+中 - 如果您只使用EXEC,則不會。

我強烈推薦閱讀The Curse and Blessing of Dynamic SQL

0

對於一些這種複雜,可能要你當用戶選擇他們的標準更新會話表。然後,您可以將會話表加入到您的項目表中。

該解決方案可能無法很好地擴展到數以千計的用戶,所以要小心。

+0

比爾你能提供更多的信息嗎?這是一個有趣的想法。下面的其他想法與我的想法是一致的和相似的......我唯一的問題是,有些人可能有50多個輸入,所以我想看看我是否完全理解你在說什麼。 – scarpacci 2010-07-23 20:24:31

+0

我的想法與鮑勃的想法基本相同。他使用特定於連接的臨時表,因此他們在搜索結束時自行清理。只要你沒有大量的併發用戶(和大量的併發臨時表),這個工作就很好。 我會使用永久表並添加某種類型的會話標識符,以便您可以區分用戶A的標準和用戶B的標準。你必須自己清理它,但縮放會更好一點。 – Bill 2010-07-23 20:32:30

0

如果您要創建動態SQL,則使用OR方法或IN方法無關緊要。 SQL Server將以相同的方式處理這些語句(可能在某些情況下的變化很小)。

您也可以考慮在此場景中使用臨時表。您可以將每個條件的選擇插入臨時表(例如#tmpColor,#tmpSize,#tmpMake等)。然後你可以創建一個非動態的SELECT語句。像下面的內容可能工作:

SELECT <column list> 
FROM MyTable 
WHERE MyTable.ColorID in (SELECT ColorID FROM #tmpColor) 
    OR MyTable.SizeID in (SELECT SizeID FROM #tmpSize) 
    OR MyTable.MakeID in (SELECT MakeID FROM #tmpMake) 

動態OR/IN和臨時表的解決方案正常工作,如果每個條件是獨立的其他條件。換句話說,如果您需要選擇其中((顏色爲紅色,尺寸爲中等)或(顏色爲綠色且尺寸較大)的行,則您需要嘗試其他解決方案。

1

我會建議做的是創建一個函數,該函數需要makeIds,colorIds等的分隔列表。這可能是一個int(或任何您的密鑰)。並把它們分成一張桌子給你。

您的SP會按照上面所述的方式列出製造商,顏色等。

YourSP '1,4,7,11', '1,6,7', '6' ....

裏面的SP,你會打電話給你劃分功能,它會返回一個表 -

SELECT * FROM 
Cars C 
JOIN YourFunction(@models) YF ON YF.Id = C.ModelId 
JOIN YourFunction(@colors) YF2 ON YF2.Id = C.ColorId 

然後,如果他們選擇什麼,他們什麼也得不到。如果他們選擇一切,他們會得到一切。

+0

請注意,只有在您的ID客戶端使用名稱/值對排序時,這纔會起作用。 – 2010-07-23 20:08:44

+0

感謝邁克,這與我在另一場景中所做的相似......確實有道理。 – scarpacci 2010-07-23 20:23:45