Необходим запрос: соответствующие ключевые слова - принято и заблокировано - SQL Server 2008 / C # - PullRequest
1 голос
/ 16 августа 2010

Я задавал этот вопрос ранее, но я изменил структуру таблицы на основе рекомендаций.Итак, вот вопрос с новыми таблицами и некоторыми дополнительными требованиями.У меня есть следующие таблицы:

Продукты
ID BIGINT
Имя VARCHAR (64)
Category1_ID INT
Category2_ID INT
Category3_ID INT

Категории
ID BIGINT Имя VARCHAR (64)

Product_Keywords
PRODUCT_ID BIGINT (FK to Products)
Ключевое слово VARCHAR (64)

User_Interests
ID BIGINT
USER_ID BIGINT (FK TO Users)
Category_ID INT

Accepted_Keywords
USER_INTEREST_ID BIGINT (FK to User_Interests)
Ключевое слово VARCHAR (64)

Blocked_Keywords
USER_INTEREST_ID BIGINT (FK для User_Interests)
Ключевое слово VARCHAR (64)

1040 *1040* 1040

Продукт (таблица «Продукты») может принадлежать от 1 до 3 категорий (как минимум, одной), поэтому Категория 1 всегда указывается, но Категория 2 и Категория 3 могут быть или не быть нулевыми.Продукт может иметь 0 или более ключевых слов (Product_Keywords).

Пользователь может указать одну или несколько категорий интересов (User_Interests).Каждая интересующая категория может иметь ноль или более принятых ключевых слов (Accepted_Keywords).У него также может быть ноль или более заблокированных ключевых слов (Blocked_Keywords).

Я хотел бы знать продукты, представляющие интерес для данного пользователя, на основе категорий, сопоставляемых в дополнение к следующим правилам:
1. ЕслиНЕТ ключевых слов Accept или Block, тогда соответствие категории достаточно
2. Если в Accept есть ключевые слова, то должно быть как минимум 1 соответствие ключевых слов между Accept & Product_Keywords
3. Если в Block есть ключевые слова, то должно бытьнет совпадений между Block & Product_Keywords
4. Комбинация 2 & 3

В идеале я хотел бы сделать это в запросе SQL.Я открыт для хранимых процедур Managed или T-SQL в этом порядке.Я использую SQL Server 2008, C # и .NET 4.0.

Спасибо!

1 Ответ

1 голос
/ 17 августа 2010
CREATE PROCEDURE GetProductsOfInterest
    @USER_ID BIGINT NOT NULL
AS
SET NOCOUNT ON

SELECT p.ID, p.Name
FROM   Products p
INNER JOIN User_Interests ui
ON     ui.USER_ID = @USER_ID
AND    (ui.Category_ID = p.Category1_ID OR
        ui.Category_ID = p.Category2_ID OR
        ui.Category_ID = p.Category3_ID)
WHERE  (NOT EXISTS (SELECT 1 FROM Product_Keywords pk1
            WHERE  pk1.PRODUCT_ID = p.ID
            AND    EXISTS (SELECT 1 FROM Blocked_Keywords bk1
                   WHERE  bk1.USER_INTEREST_ID = ui.ID
                   AND    bk1.Keyword = pk1.Keyword)) AND
    (NOT EXISTS (SELECT 1 FROM Accepted_Keywords ak1
             WHERE  ak1.USER_INTEREST_ID = ui.ID) OR
     EXISTS (SELECT 1 FROM Product_Keywords pk2
         WHERE  pk2.PRODUCT_ID = p.ID
         AND    EXISTS (SELECT 1 FROM Accepted_Keywords ak2
                    WHERE  ak2.USER_INTEREST_ID = ui.ID
                AND    ak2.Keyword = pk2.Keyword)))
GO

Я не могу обещать, что это сработает полностью, учитывая отсутствие хорошего способа отладки на данный момент. В этом коде предполагается, что если ключевое слово появляется в списках «Принятые» и «Заблокированные» для данного интереса, список «Заблокированные» имеет преимущественную силу. Кроме того, списки «Принятые» и «Блокированные» применяются только к одной конкретной категории интересов для клиента. Наконец, если объект относится к более чем одной категории интересов, он может отображаться один раз для каждой категории интересов с учетом принятых / заблокированных правил для каждой категории интересов.

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

...