SQL - выберите отдельную строку с несколькими категориями - PullRequest
2 голосов
/ 11 января 2012

У меня есть три таблицы базы данных:

История

  • Идентификатор
  • Заголовок
  • Содержимое

Категория

  • Id
  • Заголовок

StoryCategory

  • StoryId
  • CategoryId

Примечание. История и категория имеют отношение «многие ко многим» (история может иметь несколько категорий, а категория может иметь несколько историй), поэтому я создал 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

Образцы данных:

  • Story

    id title content 1 naruto... 2 отбеливателя ...

  • Категория

    id title 1 фэнтези 2 действие 3 драма

  • StoryCategory

    storyId categoryId 1 1 1 2 2 1

Проблема в том, что если выбранной категории нет и если в истории есть несколько категорий, она также будет появляться несколько раз:

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

Я действительно знаю, что происходит, но я не могу придумать лучшего решения для решения проблемы.

Ответы [ 2 ]

3 голосов
/ 11 января 2012

Используйте ключевое слово 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:

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
0 голосов
/ 11 января 2012

Если вы не ограничиваете его одной категорией, попробуйте что-то вроде этого:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...