Sql 查找所有子记录都具有给定值的所有父记录(而不仅仅是某些子记录)

Sql 查找所有子记录都具有给定值的所有父记录(而不仅仅是某些子记录),sql,ruby-on-rails,ruby-on-rails-4,has-many,belongs-to,Sql,Ruby On Rails,Ruby On Rails 4,Has Many,Belongs To,一个活动有许多参与者。参与者有一个状态字段 class Event < ActiveRecord::Base has_many :participants end class Participant < ActiveRecord::Base belongs_to :event end 这将创建类似以下SQL的SQL: SELECT events.id, participants.status as status, count(*) FROM `events` INNER

一个活动有许多参与者。参与者有一个状态字段

class Event < ActiveRecord::Base
  has_many :participants
end

class Participant < ActiveRecord::Base
  belongs_to :event
end
这将创建类似以下SQL的SQL:

SELECT events.id, participants.status as status, count(*) 
FROM `events` INNER JOIN `participants` 
ON `participants`.`event_id` = `events`.`id` 
WHERE (`participants`.`status` != 'present') 
GROUP BY participants.event_id HAVING count(*) > 0
这几乎奏效了。问题是,如果@participant.event_id范围内的参与者行之一的状态为away,则仍然会获取该事件,因为至少有一些同级记录的状态与present之外的状态相同

我需要确保我过滤掉每一个事件记录和所有参与者的现状


我对ActiveRecord或SQL解决方案持开放态度。

如果您试图通过查找事件的ID(其中一个人的状态不是当前状态)来进行查询,然后在这种情况下查找所有唯一的事件,该怎么办

unique_event_ids = Participant.where.not(status: "present").pluck(:event_id).uniq
events_you_want = Event.where(unique_event_ids)

如果您试图通过查找某人的状态不是present的事件的ID来进行查询,然后查找所有唯一的事件(在这种情况下),该怎么办

unique_event_ids = Participant.where.not(status: "present").pluck(:event_id).uniq
events_you_want = Event.where(unique_event_ids)

如果我没弄错的话,你的问题可以归类为关系划分。基本上有两种方法:

1a对于所有x:px

在SQL中,必须将其转换为:

1b不存在x:不存在px

对于您的问题,可能是这样的:

SELECT e.* 
FROM events e
WHERE NOT EXISTS (
    SELECT 1 
    FROM PARTICIPANTS p
    WHERE p.status <> 'present'
      AND p.event_id = e.event_id
)

这两种解决方案都未经测试,因此可能会有错误,但它应该给您一个开始

如果我做对了,您的问题可以归类为关系划分。基本上有两种方法:

1a对于所有x:px

在SQL中,必须将其转换为:

1b不存在x:不存在px

对于您的问题,可能是这样的:

SELECT e.* 
FROM events e
WHERE NOT EXISTS (
    SELECT 1 
    FROM PARTICIPANTS p
    WHERE p.status <> 'present'
      AND p.event_id = e.event_id
)

这两种解决方案都未经测试,因此可能存在错误,但它应该给您一个开始

您可以使用子选择筛选出参与者不在场的事件。不过,这可能不是最有效的方法

SELECT events.id, participants.status as status, count(*) 
FROM `events` INNER JOIN `participants` 
ON `participants`.`event_id` = `events`.`id` 
WHERE (`participants`.`status` != 'present')
AND events.id NOT IN (SELECT DISTINCT event_id FROM participants WHERE participants.status != 'present')
GROUP BY participants.event_id HAVING count(*) > 0

您可以使用子选择筛选出参与者不在场的事件。不过,这可能不是最有效的方法

SELECT events.id, participants.status as status, count(*) 
FROM `events` INNER JOIN `participants` 
ON `participants`.`event_id` = `events`.`id` 
WHERE (`participants`.`status` != 'present')
AND events.id NOT IN (SELECT DISTINCT event_id FROM participants WHERE participants.status != 'present')
GROUP BY participants.event_id HAVING count(*) > 0
我真的很喜欢

我对第一个示例做了一个简单的修改,它只返回包含参与子记录的事件父记录,并且处理速度比查找每个事件的计数快得多

SELECT e.* 
FROM events e
INNER JOIN participants p ON p.event_id = e.event_id
WHERE NOT EXISTS (
  SELECT 1 
  FROM PARTICIPANTS p
  WHERE p.status <> 'present'
  AND p.event_id = e.event_id
)
GROUP BY e.event_id
我真的很喜欢

我对第一个示例做了一个简单的修改,它只返回包含参与子记录的事件父记录,并且处理速度比查找每个事件的计数快得多

SELECT e.* 
FROM events e
INNER JOIN participants p ON p.event_id = e.event_id
WHERE NOT EXISTS (
  SELECT 1 
  FROM PARTICIPANTS p
  WHERE p.status <> 'present'
  AND p.event_id = e.event_id
)
GROUP BY e.event_id

我需要一个解决方案,而其他答案对我来说并不适用,但这是我的解决方案。我编写了两个函数,一个用于获取子记录的总数,另一个用于获取满足特定条件的子记录的总数。然后我比较了两个函数。如果结果算术/求值等于零,则表示所有记录都符合真实标准。很简单

Select p.pid, p.Name, p.Group, udfn_TotalChildrenRecords(p.pid), udfn_TotalChildrenRecordsThatAreTrue(p.pid) 
From Parent AS p INNER JOIN Child AS c ON Parent.pid = child.pid
GROUP BY p.pid, p.Name, p.Group
HAVING udfn_TotalChildrenRecords(p.pid) - udfn_TotalChildrenRecordsThatAreTrue(p.pid) = 0

我需要一个解决方案,而其他答案对我来说并不适用,但这是我的解决方案。我编写了两个函数,一个用于获取子记录的总数,另一个用于获取满足特定条件的子记录的总数。然后我比较了两个函数。如果结果算术/求值等于零,则表示所有记录都符合真实标准。很简单

Select p.pid, p.Name, p.Group, udfn_TotalChildrenRecords(p.pid), udfn_TotalChildrenRecordsThatAreTrue(p.pid) 
From Parent AS p INNER JOIN Child AS c ON Parent.pid = child.pid
GROUP BY p.pid, p.Name, p.Group
HAVING udfn_TotalChildrenRecords(p.pid) - udfn_TotalChildrenRecordsThatAreTrue(p.pid) = 0

Participant.where.notstatus:present可能会抓取一个具有与present不相等状态的对等方的参与者。这破坏了ID的收集。任何事件都不能有任何不等于present.participant.where.notstatus的子参与者:present将潜在地抓取具有状态不等于present的对等方的参与者。这破坏了ID的收集。任何活动都不能有不等于当前的任何子参与者。我从中得到0行,尽管理论上看起来不错。谢谢。虽然理论上看起来不错,但我从中得到了0行。谢谢。在尝试了这两个优秀的示例之后,第一个示例返回所有事件家长,即使是没有参与儿童记录的家长,因为他们符合标准。第二个示例仅返回包含参与者子记录的事件父记录,但计数*需要时间来处理。在尝试了这两个优秀示例后,第一个示例返回所有事件父记录,即使没有参与子记录,因为它们符合条件。第二个示例仅返回带有参与者子记录的事件父记录,但计数*需要时间来处理。