我们有:
class Campaign::Item < ActiveRecord::Base
belongs_to :campaign
has_many :criteria
end
class Campaign::Item::Criterium < ActiveRecord::Base
belongs_to :campaign_item
# This model has a +type+ field.
end
class Campaign::Item::Criterium::Gender < Campaign::Item::Criterium
belongs_to :campaign_item
# This model uses the a +gender+ field.
end
class Campaign::Item::Criterium::Age < Campaign::Item::Criterium
belongs_to :campaign_item
# This model uses the +age_min+ and +age_max+ fields.
end
class User
# This model has a +gender+ and +birth_date+ field.
end
如您所见,用户可以使用其中的项目制作广告系列。 每个广告系列项目都可以根据性别和年龄制定许多条件。
现在我们正在尝试列出与当前用户信息匹配的所有广告系列项目。
例如:
当前用户为female
并且25 years old
此用户应该能够看到只有female Gender
标准的项目
它还应该能够看到具有female Gender
标准和Age between 18 and 30 years old
标准的项目。
但是,此用户不应该看到具有female Gender
标准和Age between 30 and 35 years old
标准的项目。
因此,此处的目标是返回所有Campaign::Item
,其中 all 的条件与当前用户的信息相匹配。
目前,我们只设法返回Campaign::Item
,其中至少一个标准与当前用户的信息相匹配。
以下是我们尝试实现此目标的一些查询示例:
SELECT "campaign_items".*
FROM "campaign_items"
INNER JOIN "campaign_item_criteria"
ON "campaign_item_criteria"."campaign_item_id" = "campaign_items"."id"
WHERE
("campaign_item_criteria"."type" = 'Campaign::Item::Criterium::Gender'
AND ("campaign_item_criteria"."gender" IS NULL
OR "campaign_item_criteria"."gender" = 'female'))
AND ("campaign_item_criteria"."type" = 'Campaign::Item::Criterium::Age'
AND ("campaign_item_criteria"."age_min" IS NULL
OR "campaign_item_criteria"."age_min" <= 17)
AND ("campaign_item_criteria"."age_max" IS NULL
OR "campaign_item_criteria"."age_max" >= 17))
这个不起作用,因为它试图找到同时具有Campaign::Item::Criterium::Gender
和Campaign::Item::Criterium::Age
类型的标准,显然,这不会很快就会出现这种情况。
SELECT "campaign_items".*
FROM "campaign_items"
INNER JOIN "campaign_item_criteria"
ON "campaign_item_criteria"."campaign_item_id" = "campaign_items"."id"
WHERE
CASE
WHEN "campaign_item_criteria"."type" = 'Campaign::Item::Criterium::Gender'
AND "campaign_item_criteria"."gender" = 'female'
THEN 1
WHEN "campaign_item_criteria"."type" = 'Campaign::Item::Criterium::Age'
AND "campaign_item_criteria"."age_min" <= 17
AND ("campaign_item_criteria"."age_max" IS NULL OR "campaign_item_criteria"."age_max" >= 17)
THEN 1
ELSE 0
END = 1
即使其他条件与用户的信息不匹配,只要一个标准与用户的信息匹配,它就会返回Campaign::Item
,这也不起作用。< / p>
现在我们的想法已经不多了。我们是否有机会在纯SQL中按预期工作?有人有任何导致吗?
提前致谢!
答案 0 :(得分:0)
为什么不在where子句中使用exists
? (简写因为f ***再次输入所有内容)
SELECT ci.*
FROM campaign_items ci
WHERE exists (select 1
from campaign_item_criteria cic
where cic.campaign_item_id = ci.id
and cic.type = '::gender'
and (cic.gender = 'female' or cic.gender is null)
)
and exists (select 1
from campaign_item_criteria cic
where cic.campaign_item_id = ci.id
and cic.type = '::age'
and (cic.age = '35' or cic.age is null)
)
答案 1 :(得分:0)
我能够找到一个完全符合我要求的查询:
SELECT DISTINCT "campaign_items".*
FROM "campaign_items"
INNER JOIN "campaign_item_criteria"
ON "campaign_item_criteria"."campaign_item_id" = "campaign_items"."id"
WHERE
(NOT EXISTS (SELECT 1
FROM "campaign_item_criteria"
WHERE "campaign_item_criteria"."campaign_item_id" = "campaign_items"."id"
AND "campaign_item_criteria"."type" = 'Campaign::Item::Criterium::Gender')
OR EXISTS (SELECT 1
FROM "campaign_item_criteria"
WHERE "campaign_item_criteria"."campaign_item_id" = "campaign_items"."id"
AND "campaign_item_criteria"."type" = 'Campaign::Item::Criterium::Gender'
AND "campaign_item_criteria"."gender" = 'female'))
AND (NOT EXISTS (SELECT 1
FROM "campaign_item_criteria"
WHERE "campaign_item_criteria"."campaign_item_id" = "campaign_items"."id"
AND "campaign_item_criteria"."type" = 'Campaign::Item::Criterium::Age')
OR EXISTS (SELECT 1
FROM "campaign_item_criteria"
WHERE "campaign_item_criteria"."campaign_item_id" = "campaign_items"."id"
AND "campaign_item_criteria"."type" = 'Campaign::Item::Criterium::Age'
AND "campaign_item_criteria"."age_min" <= 17
AND ("campaign_item_criteria"."age_max" IS NULL
OR "campaign_item_criteria"."age_max" >= 17)))
这样就可以查询2个条件并且它有4个子查询。我们已经知道我们最终会得到~10个不同的标准。因此,最终请求的总共20个子查询
目前(有2个标准),数据库中需要大约2.5ms,2 Campaign::Item
,数据库需要大约16ms和2 000 Campaign::Item
。它并不像我们想象的那样具有指数性,因此我们会说它足够好&#39;。
我们现在要保留这个 有没有人可以添加任何内容或改进任何路径?