SQL - 选择具有多个类别的不同行

时间:2012-01-11 05:49:50

标签: sql sql-server-2008 razor

我有三个数据库表:

故事

  • 编号
  • 标题
  • 内容

类别

  • Id
  • 标题

StoryCategory

  • StoryId
  • 类别ID

注意:故事和类别具有多对多关系(一个故事可以有多个类别,一个类别可以有多个故事)所以我创建了StoryCategory。此外,一个故事可以没有类别。

我还有一个网页(我使用剃须刀):

<form action="" method="get">
    <label for="keyword">Keyword:</label>
    <input name="keyword" type="text" value="@Page.Keyword" />
    <label for="category">Category:</label>
    <select name="category">
        <option value="">All</option>
    @foreach(var category in Page.Categories)
    {
        <option value=@category.Id @(category.Id == Page.Category? "selected=selected" : "")>@category.Title</option>
    }
    </select>
    <input type="submit" value="Search" />
</form> 

为简单起见,此页面允许用户输入关键字以搜索特定故事,并且还允许用户选择故事所属的类别。

我无法找到附加到特定类别的故事的方法。这是我的第一个代码(忽略关注类别的关键字):

select s.title --columns will be added here such as name of category/ies, author etc.
from story as s
left join --left join so the uncategorized stories will not be excluded
storyCategory as sc
on s.id = sc.storyId
where sc.categoryId = @selectedCategory --this line is removed when there is no category selected

示例数据:

  • 故事

    id标题内容 1个火影忍者...... 2漂白...

  • 分类

    id标题 1幻想 2动作 3戏剧

  • StoryCategory

    storyId categoryId 1 1 1 2 2 1

问题是,如果没有选定的类别,如果故事有多个类别,它也会多次出现:

naruto (fantasy)
naruto (action)
bleach (fantasy)

我实际上知道发生了什么,但我无法想出解决问题的最佳解决方案。

2 个答案:

答案 0 :(得分:3)

使用DISTINCT关键字,左连接对您的WHERE条件无效

select DISTINCT
  s.title --columns will be added here such as name of category/ies, author etc.
from story as s
join storyCategory as sc--left join so the uncategorized stories will not be excluded
on s.id = sc.storyId
where sc.categoryId = @selectedCategory --this line is removed when there is no category selected

如果您需要附加到每个故事的类别列表 - 请查看并检查下一个查询。适用于sql server:

DECLARE @Stories TABLE(Id INT IDENTITY PRIMARY KEY, NAME NVARCHAR(100) NOT NULL) 
DECLARE @Categories TABLE(Id INT IDENTITY PRIMARY KEY, NAME NVARCHAR(100) NOT NULL) 
DECLARE @Fork TABLE(StoryId INT NOT NULL, CategoryId INT NOT NULL, PRIMARY KEY(StoryId, CategoryId)) 

INSERT @Stories 
VALUES ('Story1'), ('Story2'), ('Story3') 

INSERT @Categories 
VALUES ('Category1'), ('Category2'), ('Category3') 

INSERT @Fork 
VALUES(1,1), (1,2), (3,3), (2,3) 

DECLARE @selectedCategory INT = 3 

select 
s.NAME, 
( 
SELECT c.Name + ',' 
FROM @Categories c 
JOIN @Fork f ON f.CategoryId = c.Id AND f.StoryId = s.Id 
ORDER BY c.Name 
FOR XML PATH('') 
) Categories 
from @stories s

答案 1 :(得分:0)

如果您不将其限制为单个类别,请尝试以下方法:

select s.title,count(*) as NumCategories 
from story as s
left join storyCategory as sc on s.id = sc.storyId
group by s.title

您还可以使用类似的内容查找某些类别,其中显示了类别的数量以及故事所在的第一个和最后一个(基于标题字符)类别

select s.title,count(*) as NumCategories,min(sc.title),max(sc.title)
from story as s
left join storyCategory as sc on s.id = sc.storyId
group by s.title