Я совершенно не рассчитываю получить какие-либо ответы здесь, но я все равно попробую.
Так что это вышло из игры в Skyrim.Я хотел простой способ найти, какие ингредиенты можно комбинировать для приготовления разных зелий / ядов, поэтому я создал таблицу ингредиентов, в которой есть ID и имя;таблица эффектов, которая имеет идентификатор, имя, флаг яда и флаг зелья (зелье и яд взаимоисключающие);и объединяющая таблица с идентификатором ингредиента и идентификатором эффекта.
Таким образом, каждый компонент имеет четыре различных эффекта, эффекты повторяются на нескольких ингредиентах.В игре вы можете комбинировать 2 или 3 ингредиента, и в результате получается зелье или яд со всеми эффектами, которые совпадают по крайней мере с 2 из используемых ингредиентов.Поэтому, если вы используете 3 ингредиента, и эффект 1 относится как к ингредиенту 1, так и к ингредиенту 2, а эффект 2 - как к ингредиенту 1, так и к ингредиенту 3, ваш результат будет зельем / ядом, обладающим эффектом 1 и эффектом.
Я смог придуматьмой собственный запрос, который покажет каждую возможную комбинацию из 2 ингредиентов, которая создает зелье без ядовитых эффектов.Сначала мне нужно найти каждую возможную комбинацию из 2 ингредиентов, которая имеет только совпадающие эффекты, которые не являются «ядом»:
SELECT i1.UniqIngredient UniqIngredient1, i2.UniqIngredient UniqIngredient2
FROM Ingredient i1
CROSS JOIN Ingredient i2
INNER JOIN IngredientEffectJT jt1 ON i1.UniqIngredient = jt1.UniqIngredient
INNER JOIN IngredientEffectJT jt2 ON i2.UniqIngredient = jt2.UniqIngredient
INNER JOIN Effect e ON jt1.UniqEffect = e.UniqEffect AND jt2.UniqEffect = e.UniqEffect
WHERE i1.UniqIngredient < i2.UniqIngredient
GROUP BY i1.UniqIngredient, i2.UniqIngredient
HAVING SUM(e.Poison) = 0
Ингредиент перекрестно соединен с Ингредиентом, чтобы получить каждую комбинацию, но потому что порядок ингредиентов неНе имеет значения, я бы в итоге удвоил результаты.Вот почему ГДЕ проверяет i1.UniqIngredient
Затем я использую этот результат в качестве таблицы, к которой я присоединяюсь к Ингредиенту иТаблицы эффектов, чтобы получить список всех возможных 2 комбинаций ингредиентов, которые производят зелья, и какие эффекты имеет каждая комбинация:
SELECT i1.Name, i2.Name, e.Name
FROM (SELECT i1.UniqIngredient UniqIngredient1, i2.UniqIngredient UniqIngredient2
FROM Ingredient i1
CROSS JOIN Ingredient i2
INNER JOIN IngredientEffectJT jt1 ON i1.UniqIngredient = jt1.UniqIngredient
INNER JOIN IngredientEffectJT jt2 ON i2.UniqIngredient = jt2.UniqIngredient
INNER JOIN Effect e ON jt1.UniqEffect = e.UniqEffect AND jt2.UniqEffect = e.UniqEffect
WHERE i1.UniqIngredient < i2.UniqIngredient
GROUP BY i1.UniqIngredient, i2.UniqIngredient
HAVING SUM(e.Poison) = 0) il
INNER JOIN Ingredient i1 ON il.UniqIngredient1 = i1.UniqIngredient
INNER JOIN Ingredient i2 ON il.UniqIngredient2 = i2.UniqIngredient
INNER JOIN IngredientEffectJT jt1 ON i1.UniqIngredient = jt1.UniqIngredient
INNER JOIN IngredientEffectJT jt2 ON i2.UniqIngredient = jt2.UniqIngredient
INNER JOIN Effect e ON jt1.UniqEffect = e.UniqEffect AND jt2.UniqEffect = e.UniqEffect
ORDER BY i1.Name, i2.Name, e.Name
Используя тот же запрос, я могу найти 2 комбинации ядовитых ингредиентов, которые не имеют эффектов зелья, простоизменив строку HAVING, чтобы проверить e.Potion вместо e.Poison.
Это все хорошо и хорошо, но когда я хочу представить третий ингредиент, вот тут-то и становится сложно.Я в тупике.Я могу изменить этот запрос, чтобы проверить 3 ингредиента, которые имеют одинаковый эффект, но это не то, что я хочу.Я хочу найти третий ингредиент, который по-разному влияет на один из ингредиентов.
Любая помощь?
РЕДАКТИРОВАТЬ
Обновление: так что после нескольких часов борьбы с этим я придумал большой, уродливый, медленный, трудный для выполнения запрос (я даже не помню, почему мне пришлось выполнить это безумное условие соединения в таблице EffectНо когда я изменяю его, весь запрос выполняется в 2 раза медленнее, так что на самом деле он быстрее, чем у меня, хотя я не знаю почему ...), что почти делает то, что я хочу.Это может быть как можно ближе, если только у кого-то нет других идей или способ улучшить мой новый запрос.
SELECT DISTINCT il.Name1, il.Name2, il.Name3, e.Name
FROM
(SELECT DISTINCT i1.UniqIngredient Ingredient1, i1.Name Name1, i2.UniqIngredient Ingredient2, i2.Name Name2, i3.UniqIngredient Ingredient3, i3.Name Name3
FROM Ingredient i1
INNER JOIN Ingredient i2 ON i1.UniqIngredient < i2.UniqIngredient
INNER JOIN Ingredient i3 ON i2.UniqIngredient < i3.UniqIngredient
INNER JOIN IngredientEffectJT jt1 ON i1.UniqIngredient = jt1.UniqIngredient
INNER JOIN IngredientEffectJT jt2 ON i2.UniqIngredient = jt2.UniqIngredient
INNER JOIN IngredientEffectJT jt3 ON i3.UniqIngredient = jt3.UniqIngredient
INNER JOIN Effect e ON (jt1.UniqEffect = e.UniqEffect AND (jt2.UniqEffect = e.UniqEffect OR jt3.UniqEffect = e.UniqEffect)) OR (jt2.UniqEffect = e.UniqEffect AND jt3.UniqEffect = e.UniqEffect)
WHERE (EXISTS (SELECT 1
FROM IngredientEffectJT jt1
INNER JOIN IngredientEffectJT jt2 ON jt1.UniqEffect = jt2.UniqEffect
WHERE jt1.UniqIngredient = i1.UniqIngredient
AND jt2.UniqIngredient = i2.UniqIngredient)
AND (EXISTS (SELECT 1
FROM IngredientEffectJT jt1
INNER JOIN IngredientEffectJT jt3 ON jt1.UniqEffect = jt3.UniqEffect
WHERE jt1.UniqIngredient = i1.UniqIngredient
AND jt3.UniqIngredient = i3.UniqIngredient)
OR EXISTS (SELECT 1
FROM IngredientEffectJT jt2
INNER JOIN IngredientEffectJT jt3 ON jt2.UniqEffect = jt3.UniqEffect
WHERE jt2.UniqIngredient = i2.UniqIngredient
AND jt3.UniqIngredient = i3.UniqIngredient)))
OR (EXISTS (SELECT 1
FROM IngredientEffectJT jt1
INNER JOIN IngredientEffectJT jt3 ON jt1.UniqEffect = jt3.UniqEffect
WHERE jt1.UniqIngredient = i1.UniqIngredient
AND jt3.UniqIngredient = i3.UniqIngredient)
AND EXISTS (SELECT 1
FROM IngredientEffectJT jt2
INNER JOIN IngredientEffectJT jt3 ON jt2.UniqEffect = jt3.UniqEffect
WHERE jt2.UniqIngredient = i2.UniqIngredient
AND jt3.UniqIngredient = i3.UniqIngredient))
GROUP BY i1.UniqIngredient, i1.Name, i2.UniqIngredient, i2.Name, i3.UniqIngredient, i3.Name
HAVING SUM(e.Poison) = 0) il
INNER JOIN IngredientEffectJT jt1 ON il.Ingredient1 = jt1.UniqIngredient
INNER JOIN IngredientEffectJT jt2 ON il.Ingredient2 = jt2.UniqIngredient
INNER JOIN IngredientEffectJT jt3 ON il.Ingredient3 = jt3.UniqIngredient
INNER JOIN Effect e ON (jt1.UniqEffect = e.UniqEffect AND (jt2.UniqEffect = e.UniqEffect OR jt3.UniqEffect = e.UniqEffect)) OR (jt2.UniqEffect = e.UniqEffect AND jt3.UniqEffect = e.UniqEffect)
ORDER BY il.Name1, il.Name2, il.Name3, e.Name
Во внутреннем запросе:
FROM Ingredient i1
INNER JOIN Ingredient i2 ON i1.UniqIngredient < i2.UniqIngredient
INNER JOIN Ingredient i3 ON i2.UniqIngredient < i3.UniqIngredient
Это создает каждую возможную комбинацию из 3 ингредиентов, где порядок не имеет значения и ничего не повторяется.Затем Joins to IngredientEffectJT и Effect ... Я на самом деле не помню, для чего предназначено безумное соединение в Effect.Глядя на это, я подумал, что нужно убедиться, что эффект существует как минимум на 2 ингредиентах, но это то, что делает предложение WHERE.И упрощение этого объединения эффектов приводит к тому, что оно работает значительно медленнее, поэтому ... что угодно.
Тогда появится GROUP BY, чтобы я мог посчитать количество подходящих ядовитых эффектов.Так как мне пришлось сгруппировать по 3 ингредиентам, я теряю индивидуальные эффекты соответствия, поэтому мне нужно снова объединить все эти ингредиенты обратно к их эффектам и найти соответствующие эффекты.
Проблема с этим запросом состоит в том, что он покажет комбинации, в которых все 3 ингредиента имеют один и тот же эффект. Эти комбинации не имеют смысла, потому что вы можете сделать то же самое, используя только 2 из 3, так что это немного расточительно.
Итак, это лучшее, что я мог придумать. Это очень медленно, поэтому, возможно, я просто сохраню его в новой таблице, чтобы в будущем было проще и быстрее снова делать запросы.