繁体   English   中英

SQL左联接值不在任何联接列中

[英]SQL LEFT JOIN value NOT in either join column

我怀疑这是一个相当普遍的情况,可能显示出我作为数据库开发人员的无能,但是无论如何这里都...

我有两个表: ProfilesHiddenProfiles ,并且HiddenProfiles表具有两个相关的外键: profile_idhidden_​​profile_id ,用于存储Profiles表中的id

可以想象,一个用户可以隐藏另一个用户(其中​​,他的个人资料ID将为HiddenProfiles表中的profile_id ),或者他可以被另一个用户隐藏 (其中他的个人资料ID将被置于hidden_​​profile_id列中)。 同样,这是一个非常常见的情况。

期望的结果:
我想对“个人档案”和“ HiddenProfiles”表进行联接(或者说实话,无论哪种查询效率最高),以查找给定个人档案既不隐藏又不隐藏的所有个人档案。

在我的脑海中,我认为这将非常简单,但是我想到的迭代似乎一直遗漏了一半的问题。 最后,我得到的结果如下所示:

SELECT "profiles".* FROM "profiles"
LEFT JOIN hidden_profiles hp1 on hp1.profile_id = profiles.id and (hp1.hidden_profile_id = 1)
LEFT JOIN hidden_profiles hp2 on hp2.hidden_profile_id = profiles.id and (hp2.profile_id = 1)
WHERE (hp1.hidden_profile_id is null) AND (hp2.profile_id is null)

不要误会我的意思,这个“有效”的方法,但是在我的内心深处,我觉得应该有更好的方法。 如果实际上没有答案,我很乐意接受比我这个问题更聪明的人的回答。 :)

值得一提的是,Postgres DB上有两个RoR模型,因此欢迎为这些约束量身定制的解决方案。


模型是这样的:

Profile.not_hidden(given_profile)

因此,要获取个人资料,我需要执行以下操作:

 Profile.not_hidden(given_profile) 

再说一次,也许这很好,但是如果有更好的方法,我会很乐意接受。

如果您只想为单个配置文件获取此列表,则可以实现一个实例方法以在ActiveRecord中有效执行相同的查询。 我所做的唯一修改是对子查询的联合执行单个联接,并将条件应用于子查询。 这将减少需要加载到内存中的列,并希望更快(您需要对数据进行基准测试以确保):

class Profile < ActiveRecord::Base
  def visible_profiles
    Profile.joins("LEFT OUTER JOIN (
      SELECT profile_id p_id FROM hidden_profiles WHERE hidden_profile_id = #{id}
      UNION ALL
      SELECT hidden_profile_id p_id FROM hidden_profiles WHERE profile_id = #{id}
    ) hp ON hp.p_id = profiles.id").where("hp.p_id IS NULL")
  end
end

由于此方法返回ActiveRecord范围,因此可以根据需要链接其他条件:

Profile.find(1).visible_profiles.where("created_at > ?", Time.new(2015,1,1)).order(:name)

我个人从未喜欢过join = null方法。 我发现它与直觉相反。 您要进行联接,然后将结果限制为不匹配的记录。

我会更倾向于

SELECT id FROM profiles p
WHERE 
NOT EXISTS 
 (SELECT * FROM hidden_profiles hp1 
  WHERE hp1.hidden_profile_id = 1 and hp1.profile_id = p.profile_id)
AND
  NOT EXISTS (SELECT * FROM hidden_profiles hp2 
  WHERE hp2.hidden_profile_id = p.profile_id and hp2.profile_id = 1)

但是您将需要对它进行一些实际的解释,以确保最有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM