代码之家  ›  专栏  ›  技术社区  ›  David

从列表中选择子记录的记录

  •  1
  • David  · 技术社区  · 14 年前

    问题

    我正在尝试编写一个存储过程来选择 纽西姆 记录每个 纽西姆 拥有所有的 类别 这是一个列表。如果列表是空的,那么它应该返回所有的新闻条目。

    NewsItem     NewsItemCategories     Category
    --------     ------------------     --------
    NewsID       NewsID                 CategoryID
    Post         CategoryID             CategoryName
    

    我将以逗号分隔的类别名称列表传递给存储过程,并创建了一个函数,该函数返回这些类别的表。

    exec sp_GetNewsItems 'sport,football,hockey'
    
    EntityNameColumn - table returned from my function BuildStringTable
    ----------------
    sport
    finance
    history
    

    我试过什么

    select NI.NewsID, NI.Post
    from NewsItem NI
    where (@pCategories = '' or
        (select COUNT(*)
        from NewsItemCategories NIC
        inner join Category C on NIC.CategoryID = C.CategoryID
        inner join BuildStringTable(@pCategories) CT on C.CategoryName = CT.EntityNameColumn
    where NIC.NewsID = NI.NewsID) > 0)
    

    问题

    如果将单个类别名称传递给查询,则该查询将起作用,但是传递多个类别名称时,该查询将不起作用。在上面的示例查询中,它应该返回包含, 至少 分类,体育,足球,曲棍球。

    1 回复  |  直到 14 年前
        1
  •  1
  •   mdma    14 年前

    If you are using sql 2005 or newer, you can use the EXCEPT 运算符查找包含所有必需类别的新闻项。或者更准确地说,查找在新闻项类别名称集合中未找到的类别列表中没有名称的新闻项。

    select NI.NewsID, NI.Post
    from NewsItem NI
    where (@pCategories = '' or
        NOT EXISTS (select EntityNameColumn FROM BuildStringTable(@pCategories) 
            EXCEPT 
                  Select CategoryName FROM NewsItem ni 
                  join NewsItemCategories nic ON ni.NewsID=nic.NewsID
                  join Category c ON c.CategoryID = nic.CategoryID 
            WHERE ni.NewsID=NI.NewsID))
    

    To do this without the EXCEPT operator looks like this:

    where (@pCategories = '' or
        NOT EXISTS (select EntityNameColumn FROM BuildStringTable(@pCategories) ct 
            LEFT OUTER JOIN 
                  (Select CategoryName FROM NewsItem ni 
                  join NewsItemCategories nic ON ni.NewsID=nic.NewsID
                  join Category c ON c.CategoryID = nic.CategoryID
                  WHERE ni.NewsID=NI.NewsID) nicn
            WHERE nicn.CategoryName IS NULL)