I’m having a little trouble with a SQL query, and thought I’d solicit the wisdom of the crowd to see what I’m missing. I’m pretty sure the below works, but it seems really poor and I’m wondering if there’s a smarter way (ideally using joins instead of sub-selects) to do this.
The Problem
Let’s say I have some tables:
Prize
- PrizeId
RulePrize_Map
- PrizeId
- RuleId
Rule
- RuleId
Conditional
- ConditionalId
- RuleId
- InputId
- ExpectedValue (bit)
Input
- InputId
A Prize is won when at least one Rule is true. A Rule is true when all of its Conditionals are true. A Conditional is “true” when its InputId is either present or not present in the Input table, as designated by the ExpectedValue field. This could perhaps be treated as equivalent to: Count(InputId in Input table) = ExpectedValue for the Conditional's InputId.
Some Examples:
Conditional (InputId = 11, ExpectedValue = 1) -> True if InputId 11 in Input Table
Conditional (InputId = 12, ExpectedValue = 0) -> True if Inputid 12 NOT in Input Table
My Goal
I want to get all Prizes where at least one Rule is “true”. I would settle for: “All Rules that are true”.
My Attempt
select p.PrizeId from Prize p INNER JOIN RulePrize_Map rpm ON rpm.PrizeId = p.PrizeId
WHERE p.PrizeId IN
(select r.PrizeId from Rule r
where
(select count(*) from Conditional c1 where c1.RuleId = r.RuleId)
=
(select count(*) from Conditional c2
where c2.RuleId = r.RuleId AND
(select count(*) from Input i where i.InputId = c2.InputId) = c2.ExpectedValue
)
)
GROUP BY p.prizeId
The question change a bit, so I have redone the answer…