Я довольно новичок в работе с базами данных, но теперь совершенно без опыта. Однако я застрял на проблеме. Мне нужно сформулировать SQL-запрос, который возвращает все статьи, совместимые с набором других статей (произвольного размера). Запрос должен быть сгенерирован сценарием в приложении для поиска статей, в котором пользователь может ввести список статей, с которыми любые найденные статьи должны быть использованы (совместимы).

Итак, для списка артикулов с номерами A, B, ..., N вопрос следующий:
"Дайте мне все статьи, совместимые с A и B и ... и N"

Вопрос касается только одной таблицы;
Совместимо
artOne
artTwo

Каждая запись в Compatible представляет отношение совместимости, так что статьи A и B совместимы, если есть запись с номером статьи A в одном столбце и B в другом. NB порядок не имеет значения для совместимости.

Теперь, имея список статей, я хочу иметь возможность сгенерировать запрос, который возвращает все совместимые статьи.

Например, рассмотрим таблицу
Совместимо

A  B
----
1  2
3  1
3  4

Если бы мне были нужны все статьи, совместимые с [1], запрос вернул бы [2, 3].
Запрос, сгенерированный списком [2, 3], вернет [1].
В то время как запрос, сгенерированный из списка [1, 3], генерирует пустой список.

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

Итак, мой вопрос: есть ли способ смоделировать базу данных, чтобы эта конкретная проблема решалась более простым способом, или, в любом случае, может ли кто-нибудь помочь мне сформулировать запрос и то, как он изменяется с переменным количеством входных данных. Любые указания на чтение по этой теме также очень приветствуются.

Большое спасибо

Marco

sql
2
mahju 7 Июл 2009 в 12:01
1
Определите структуру таблицы и подробно объясните, какой результат вы хотите
 – 
KuldipMCA
7 Июл 2009 в 13:27

2 ответа

Лучший ответ
SELECT  id
FROM    (
        SELECT  B AS id
        FROM    compat
        WHERE   A IN (list)
        UNION
        SELECT  A
        FROM    compat
        WHERE   B IN (list)
        ) q
GROUP BY
        id
HAVING  COUNT(*) = @cnt

, где @cnt - общее количество элементов в вашем списке.

Чтобы это работало, вы должны убедиться, что ни одна пара совместимости не имеет двух записей в таблице (т. Е. Наличие сразу (1, 2) и (2, 1) - это плохо).

Лучше всего иметь два ограничения: одно гарантирует, что пара уникальна, а другое проверяет, что статья с наименьшим id будет первой:

ALTER TABLE compat ADD CONSTRAINT ux_compat_ab UNIQUE (A, B)
ALTER TABLE compat ADD CONSTRAINT cc_compat_order CHECK (A < B)

Если вы сделаете это, вы можете заменить UNION на более эффективный UNION ALL:

SELECT  id
FROM    (
        SELECT  B AS id
        FROM    compat
        WHERE   A IN (list)
        UNION ALL
        SELECT  A
        FROM    compat
        WHERE   B IN (list)
        ) q
GROUP BY
        id
HAVING  COUNT(*) = @cnt
1
Quassnoi 7 Июл 2009 в 18:39

Выберите * из статьи внутреннее соединение compatTbl ct на a.Id = ct.ArticleAID, где ct.ArticleBID в (список идентификаторов находится здесь)

0
joelypollyjoelypolly 7 Июл 2009 в 13:53