2015-10-15 44 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