2015-10-15 45 views
3

我需要幫助才能在更大的CTE查詢中實現篩選器。TSQL - IN子句返回空時的替代結果集

想象一下這樣的情景:可能屬於幾個類別的項目

  • 名單。
  • 用戶遵循這些類別之一。
  • 過濾器:用戶可以指定當一個類別被遵循時,他/她只想查看也屬於他/她可以指定的至少一個輔助類別的項目。

示例:用戶遵循「計算機」類別並指定僅希望查看「平板電腦」。當用戶查看「計算機」時,查詢應該只選擇也屬於「平板電腦」類別的項目。如果沒有指定過濾器,則應顯示主類別(「計算機」)的所有項目。

SQL小提琴似乎在一瞬間有一些問題,so here's a little schema and query (at the end)這說明問題

SELECT * FROM ItemsToShowWithCategories itswh_cte1 
WHERE /* Other filters AND */ 
    itswh_cte1.ItemPk IN (
     SELECT DISTINCT itswh_cte2.ItemPk 
     FROM ItemsToShowWithCategories AS itswh_cte2 
     INNER JOIN ItemsToShowWithCategories AS itswh3_cte 
      ON itswh_cte2.ItemPk=itswh3_cte.ItemPk 
     LEFT JOIN CategoriesRequiredByCategory_CTE AS crbc_cte 
      ON itswh_cte2.FkCategory=crbc_cte.FkCategoryView 
      AND crbc_cte.FkCategoryRequired=itswh3_cte.FkCategory 
     WHERE crbc_cte.FkCategoryView IS NOT NULL 
    ); 

問:我怎麼能返回所有記錄時IN子句返回空?

+0

非常好的格式問題與示例+1 – gh9

+2

爲什麼LEFT JOIN crbc_cte何時WHERE crbc_cte.FkCategoryView不爲NULL?這是一個普通的INNER JOIN。在子選擇中也不需要DISTINCT,沒有區別。 – jarlh

+0

你是對的,那是幾次不同嘗試的結果......並且在發佈之前就這樣結束了。這是我需要幫助來返回我需要的不同情況下的數據。 – ca2s7l

回答

1

好了,最明顯的將是這樣的:

WHERE /* Other filters AND */ 
    itswh_cte1.ItemPk IN (
     SELECT itswh_cte2.ItemPk 
     FROM ItemsToShowWithCategories AS itswh_cte2 
     INNER JOIN ItemsToShowWithCategories AS itswh3_cte 
      ON itswh_cte2.ItemPk=itswh3_cte.ItemPk 
     LEFT JOIN CategoriesRequiredByCategory_CTE AS crbc_cte 
      ON itswh_cte2.FkCategory=crbc_cte.FkCategoryView 
      AND crbc_cte.FkCategoryRequired=itswh3_cte.FkCategory 
     WHERE crbc_cte.FkCategoryView IS NOT NULL 
    ) 
    or 
    (SELECT count(ItemPk) 
     FROM ItemsToShowWithCategories AS itswh_cte2 
     INNER JOIN ItemsToShowWithCategories AS itswh3_cte 
      ON itswh_cte2.ItemPk=itswh3_cte.ItemPk 
     LEFT JOIN CategoriesRequiredByCategory_CTE AS crbc_cte 
      ON itswh_cte2.FkCategory=crbc_cte.FkCategoryView 
      AND crbc_cte.FkCategoryRequired=itswh3_cte.FkCategory 
     WHERE crbc_cte.FkCategoryView IS NOT NULL) = 0 

有幾個變種,你可以嘗試,如果這個表現不佳,例如使用(select top 1 ItemPk ...) is null或類似的東西。 CTE將允許您避免兩次編寫相同的SQL(如果這不是SQL生成的,則有用)。

+0

感謝您的回覆。但是,如果您指定要過濾的輔助類別,並且沒有該類別的項目,則此解決方案在最後一種情況下會失敗。它正在選擇所有項目並且應該選擇無。 – ca2s7l

+1

@ ca2s7l那麼,在這種情況下,爲什麼不檢查類別是否被選中? – Luaan

+0

如果在最後一次加入中我們改變等於所需類別的不同,它似乎正在工作。像這樣:... AND crbc_cte.FkCategoryRequired <> itswh3_cte.FkCategory。這似乎使它工作。謝謝你的幫助! – ca2s7l