Какой лучший SQL-запрос для получения связанных элементов? - PullRequest
1 голос
/ 27 июня 2009

У меня есть небольшой сайт, на котором я хочу получить похожие видео на основе тегов ... что может быть лучшим запросом MS SQL 2005 для получения похожих видео на основе тегов. Если вы можете дать запрос LINQ, это было бы здорово.

Вот схема базы данных:

CREATE TABLE Videos
    (VideoID bigint not null , 
    Title varchar(100) NULL, 
    Tags varchar(MAX) NULL, 
    isActive bit NULL  )

INSERT INTO Videos VALUES ( 1,'Beyonce Shakira - Beautiful Liar','shakira, beyonce, music, video',1)
INSERT INTO Videos VALUES ( 2,'Beyonce Ego Remix','beyonce, music, video',1)
INSERT INTO Videos VALUES ( 3,'Beyonce Ego','beyonce, music, video',1)

Что я хочу, чтобы при просмотре видео с идентификатором 1 на нем отображались похожие видео на основе его тегов, а наиболее подходящие термины должны быть на вершине.

Заранее спасибо

Ответы [ 4 ]

6 голосов
/ 27 июня 2009

Показанная вами схема, денормализованная со всеми тегами для каждого видео, вставленного в строку «Теги», плохо разработана для ваших целей - в TSQL нет разумного способа вычислить значимую «общность» между двумя строками в таком формате, и, следовательно, нет разумного способа проверить, какие пары предметов имеют относительно высокую общность и, следовательно, могут считаться «связанными». Если схема неприкасаема, вам придется реализовать определенную пользователем функцию (на C # или другом языке .NET) для этой цели, и даже тогда вам придется более или менее сканировать всю таблицу, поскольку нет разумного способа индекс на такой основе.

Если вы можете изменить схему (с еще двумя таблицами: одна для хранения тегов, а другая для связи «многие-многие» между тегами и видео), у вас могут быть лучшие перспективы; в этом случае некоторые данные о приблизительном количестве (порядка) видео, которое вы ожидаете получить, о количестве (таких же) отдельных тегов в целом и о том, какое количество тегов будет иметь видео, могут позволить разработать и эффективный способ. преследовать ваши цели.

Редактировать: по комментариям, очевидно, схема может быть изменена, хотя все еще не было дано никаких указаний относительно чисел, которые я просил, поэтому соответствующие индексы и с останутся полной загадкой. В любом случае, предположим, что схема выглядит примерно так (каждая таблица может иметь другие столбцы по своему усмотрению, просто добавьте их в запрос; длина VARCHAR также не имеет значения):

CREATE TABLE Videos (VideoID INT PRIMARY KEY,
                     VideoTitle VARCHAR(80));

CREATE TABLE Tags (TagID INT PRIMARY KEY,
                   TagText VARCHAR(20));

CREATE TABLE VideosTags (VideoID FOREIGN KEY REFERENCES Videos,
                         TagID FOREIGN KEY REFERENCES Tags,
                         PRIMARY KEY (VideoId, TagId));

т.е. просто классический учебник «отношения многие-многие».

Теперь, учитывая название видео, скажем, @MyTitle, названия 5 наиболее «связанных» с ним видео можно легко запросить, например:

WITH MyTags(TagId) AS
(
  SELECT VT1.TagID
  FROM Videos V1
  JOIN VideosTags VT1 ON (V1.VideoID=VT1.VideoID)
  WHERE V1.VideoTitle=@MyTitle
)
SELECT TOP(5) V2.VideoTitle, COUNT(*) AS CommonTags
FROM Videos V2
JOIN VideosTags VT2 ON (V2.VideoID=VT2.VideoID)
JOIN MyTags ON (VT2.TagId=MyTags.TagId)
GROUP BY V2.VideoId
ORDER BY CommonTags DESC;
0 голосов
/ 27 июня 2009

Если вы работаете на основе тегов, вам просто нужно условие WHERE tag = 'thistag' (если в одной таблице есть один тег) или WHERE tag in (SELECT tag FROM tags_table WHERE video_id = this_video_id), если вы нормализуете теги из таблицы видео, хотя любое решение, вероятно, вернет много видео, так что вам придется как-то его обрезать.

Вот тут становится интересно (и сложно); вам нужно будет не только хранить набор тегов для каждого видео, но также и оценку принадлежности для каждого отношения тегов к видео. И это становится грязным и субъективным.

С другой стороны, если вам действительно нужны "наиболее подходящие термины" (спросите, упомянутые в ваших изменениях), то я действительно думаю, что вам нужен запрос на интеллектуальный анализ данных . Анализ корзины - это метод, который обычно используется для отображения «связанных предметов», когда люди заинтересованы в взгляде на вещи, которые интересуют другие люди, этот предмет. Это немного за SQL-запрос, но если у вас есть SQL Server 2005, он входит в пакет служб Analysis Services. Стоит посмотреть!

Редактировать: теперь, когда вы опубликовали схему, я бы настоятельно предложил вам нормализовать ваше поле Tags в другой таблице. Очень трудно кодировать вокруг поля, содержащего несколько элементов с разделителями, и адресуется 1-я нормализация формы .

0 голосов
/ 27 июня 2009

Если я правильно понял ваш вопрос в том, что у вас есть таблица видео, и в этой таблице есть столбец «теги» с множеством тегов, разделенных запятой; тогда вот запрос LINQ ...

dbDataContext db = new dbDataContext();

var movies =
    from v in db.Videos
    where v.Tags.Contains("Thriller")
    select v;

Я сделал быструю таблицу с VideoId, Name и Tags. Я добавил фильм «Матрица» и добавил теги «Триллер; Действие; Драма» - этот запрос нашел запись «Матрицы».

В качестве примечания: не лучше ли иметь таблицу тегов, а не таблицу, содержащую VideoId и какие теги принадлежат им?

Просто мысль. Надеюсь, это поможет.

0 голосов
/ 27 июня 2009

Было бы лучше разделить схему так, чтобы теги находились в отдельной таблице, а затем были связаны с видео с помощью промежуточной таблицы. Примером этого может быть ...

select v.*
from Video v
  inner join VideoTag vt 
    inner join Tag t on vt.TagID = t.TagID
  on v.VideoID = vt.VideoID 
where t.Description = @tagText

где пересмотренная схема выглядит как

Видео

VideoID
Title
Description

Tag

TagID
Description

VideoTag

VideoID
TagID

В качестве альтернативы, вы можете попробовать использовать более простой запрос, такой как

select VideoID, Title, Description
from Video
where Tags like '%' + @tag + '%'

но это будет соответствовать тегам, которые содержат другие теги (например, «art» и «martial art»), поэтому я считаю, что разделение схемы - лучшее решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...