Tôi hoàn toàn không mong đợi để có được bất kỳ câu trả lời ở đây, nhưng tôi sẽ thử anyway.Làm cách nào để mở rộng truy vấn này để tìm các kết hợp hợp lệ của ba mục?
Vì vậy, điều này xuất phát từ Skyrim. Tôi muốn một cách dễ dàng để tìm kiếm những thành phần có thể được kết hợp để làm cho potions/chất độc khác nhau vì vậy tôi đã thực hiện một bảng thành phần có một ID và một tên; một bảng hiệu ứng có một ID, tên, cờ Poison và cờ Potion (thuốc và chất độc là loại trừ lẫn nhau); và một bảng tham gia có ID cho thành phần và ID có hiệu lực.
Cách hoạt động là mọi thành phần có 4 hiệu ứng khác nhau, hiệu ứng được lặp lại trên các thành phần mulitple. Trong trò chơi, bạn có thể kết hợp 2 hoặc 3 thành phần và kết quả là một loại thuốc hoặc chất độc với tất cả các hiệu ứng phù hợp với ít nhất 2 thành phần được sử dụng. Vì vậy, nếu bạn sử dụng 3 thành phần và effect1 là trên cả hai thành phần1 và ingredients2 và effect2 là trên cả hai thành phần1 và ingredients3 kết quả của bạn sẽ là một potion/chất độc có cả effect1 và effect2.
Tôi có thể tự mình tìm ra một câu hỏi sẽ hiển thị mọi kết hợp 2 thành phần có thể tạo ra một loại thuốc không có tác dụng độc. Đầu tiên tôi cần phải tìm mọi kết hợp 2 thành phần có thể là chỉ có tác dụng mà không phải là "thuốc độc" phù hợp với:
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
Ingredient là cross tham gia với thành phần để có được tất cả các kết hợp nhưng vì thứ tự của các thành phần không quan trọng , Tôi sẽ kết thúc với gấp đôi kết quả. Đó là lý do tại sao WHERE kiểm tra i1.UniqIngredient < i2.UniqIngredient. Tôi sẽ chỉ thấy mỗi kết hợp một lần và ID thấp hơn của 2 thành phần sẽ luôn ở trong cột thứ nhất. Tôi tham gia cả hai thành phần với cùng một hiệu ứng, bởi vì tôi chỉ quan tâm đến các kết hợp tạo ra kết quả. Sau đó, tôi nhóm chúng theo 2 thành phần và đếm số lượng hiệu ứng độc mà chúng chia sẻ vì tôi chỉ muốn kết hợp có 0 hiệu ứng độc.
Sau đó, tôi sử dụng kết quả này như một bảng mà tôi tham gia trở lại các bảng thành phần và có hiệu lực để có được một danh sách của tất cả các kết hợp 2 thành phần có thể là sản xuất potions, và những gì tác động từng tổ hợp có:
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
Sử dụng cùng một truy vấn tôi có thể tìm thấy 2 kết hợp chất độc thành phần không có tác dụng thuốc chỉ bằng cách thay đổi đường HAVING để kiểm tra e.Potion thay vì e.Poison.
Điều này là tốt và tốt, nhưng khi tôi muốn giới thiệu thành phần thứ 3 là nơi nó trở nên phức tạp. Tôi bối rối. Tôi có thể sửa đổi truy vấn này để kiểm tra 3 thành phần mà tất cả đều có tác dụng tương tự, nhưng đó không phải là những gì tôi muốn. Tôi muốn tìm một thành phần thứ 3 có tác dụng khác với 1 trong số các thành phần.
Bất kỳ trợ giúp nào?
EDIT
Cập nhật: Vì vậy, sau khi vật lộn với điều này trong nhiều giờ tôi đã đưa ra một lớn, xấu xí, chậm, khó có thể làm theo truy vấn (Tôi thực sự thậm chí không nhớ tại sao tôi phải làm điều đó điên cuồng tham gia điều kiện trên bảng Effect. Nhưng khi tôi thay đổi nó toàn bộ truy vấn là 2x chậm hơn vì vậy nó thực sự nhanh hơn cách tôi có nó, mặc dù tôi không biết tại sao ...), rằng gần như thực hiện những gì tôi muốn. Điều này có thể gần như tôi có thể nhận được, trừ khi ai đó có bất kỳ ý tưởng nào khác hoặc nhìn thấy một cách để cải thiện truy vấn mới của tôi.
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
Trong truy vấn bên trong:
FROM Ingredient i1
INNER JOIN Ingredient i2 ON i1.UniqIngredient < i2.UniqIngredient
INNER JOIN Ingredient i3 ON i2.UniqIngredient < i3.UniqIngredient
Điều này tạo ra mọi sự kết hợp có thể có của 3 thành phần mà tự không quan trọng và không có gì được lặp lại. Sau đó, các Joins để IngredientEffectJT và Effect ... Tôi thực sự không nhớ những gì tham gia điên trên Effect là cho. Nhìn vào nó, tôi nghĩ rằng đó là để đảm bảo một hiệu ứng tồn tại trên ít nhất 2 thành phần, nhưng đó là những gì mệnh đề WHERE đang làm. Và đơn giản hóa việc kết hợp hiệu ứng đó làm cho nó chạy chậm hơn đáng kể nên ... bất cứ điều gì.
Sau đó, GROUP BY có ở đó để tôi có thể đếm số hiệu ứng độc phù hợp. Vì tôi phải nhóm theo 3 thành phần, tôi mất các hiệu ứng kết hợp cá nhân nên tôi cần phải tham gia lại tất cả các thành phần đó trở lại hiệu ứng của chúng và tìm ra các hiệu ứng phù hợp.
Vấn đề với truy vấn này là nó sẽ hiển thị kết hợp trong đó tất cả 3 thành phần có cùng 1 hiệu ứng. Những kết hợp này là vô nghĩa bởi vì bạn có thể làm điều tương tự bằng cách chỉ sử dụng 2 trong số 3 cái đó để nó lãng phí.
Vì vậy, đây là điều tốt nhất tôi có thể nghĩ ra. Nó thực sự chậm vì vậy có lẽ tôi sẽ chỉ lưu nó vào một bảng mới để làm cho nó dễ dàng hơn và nhanh hơn để truy vấn lại trong tương lai.
Bạn có thể cung cấp bất kỳ dữ liệu mẫu nào không? – Aaron
Thử thách thú vị, tôi sẽ thử và quay lại với bạn. –
Upvote cho Skyrim tham khảo – JackAce