Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 仅当记录的所有关联记录都符合条件时才返回记录_Sql_Ruby On Rails_Ruby_Postgresql - Fatal编程技术网

Sql 仅当记录的所有关联记录都符合条件时才返回记录

Sql 仅当记录的所有关联记录都符合条件时才返回记录,sql,ruby-on-rails,ruby,postgresql,Sql,Ruby On Rails,Ruby,Postgresql,我们有: 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::Cri

我们有:

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
这一个不起作用,因为它试图找到一个同时具有
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
选择“活动项目”*
从“活动项目”
内部联接“活动项目标准”
在“活动项目标准”上,“活动项目id”=“活动项目id”
哪里
案例
当“活动项目标准”时,“键入”=“活动::项目::标准::性别”
及"运动项目标准","性别"为"女性"
那么1
当“活动项目标准”时,键入“=“活动::项目::标准::年龄”
和“活动项目标准”。“年龄最小值”=17)
那么1
其他0
结束=1
当一个条件与用户信息匹配时,即使其他条件与用户信息不匹配,ony也会返回
Campaign::Item

现在我们的想法都快用完了。我们是否有可能在纯SQL中实现预期的行为?有人有线索吗


提前谢谢

为什么不在where子句中使用
exists
?(因为f***又把这些都打出来了,所以用速记法)


我能够找到一个查询,它完全符合我的意图:

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)))
选择不同的“活动项目”*
从“活动项目”
内部联接“活动项目标准”
在“活动项目标准”上,“活动项目id”=“活动项目id”
哪里
(不存在(选择1
来自“活动项目标准”
其中“活动项目标准”。“活动项目id”=“活动项目”。“id”
和“活动项目标准”。“类型”=“活动::项目::标准::性别”)
或存在(选择1
来自“活动项目标准”
其中“活动项目标准”。“活动项目id”=“活动项目”。“id”
和“活动项目标准”。“类型”=“活动::项目::标准::性别”
及"运动项目标准","性别"为"女性")
和(不存在)(选择1
来自“活动项目标准”
其中“活动项目标准”。“活动项目id”=“活动项目”。“id”
和“活动项目标准”。“类型”=“活动::项目::标准::年龄”
或存在(选择1
来自“活动项目标准”
其中“活动项目标准”。“活动项目id”=“活动项目”。“id”
和“活动项目标准”。“类型”=“活动::项目::标准::年龄”
及"运动(项目)准则","年龄(分钟)为17岁)
这是对2个条件的查询,它有4个子查询。我们已经知道,我们最终会有10个不同的标准。最后一个请求总共有20个子查询。
目前(有2个标准),数据库中有2个
Campaign::Item
需要约2.5ms,数据库中有2000个
Campaign::Item
需要约16ms。它不像我们想象的那样是指数型的,所以我们会说它“足够好”

我们暂时保留这个。

有人有什么要添加或改进的路径吗?

您对使用复杂ON子句的每个条件的内部联接有什么想法?
存在的地方
将在得到肯定结果后立即停止,
联接
比较整体table@JohnHC您的解决方案在提供了所有现有条件的项目上运行良好。但是,如果我删除
Age
标准,用户将不再匹配。不存在的标准暗指“匹配”标准。顺便说一句,我不知道
存在
表达式,谢谢!
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)
             )
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)))