【问题标题】:Why does this double JOIN work but this similar one not work?为什么这种双重 JOIN 有效,但这种类似的无效?
【发布时间】:2014-06-10 22:15:03
【问题描述】:

这是一个 Rails 应用程序,但我只是发布 SQL。

所以,这是我的理智测试。它可以工作,并返回相同模型的两个副本。如果我不包含where,则返回多个模型的多个副本。

SELECT \"outlets\".* 
FROM \"outlets\" 
INNER JOIN \"comments\" 
ON \"comments\".\"commentable_id\" = \"outlets\".\"id\" 
AND \"comments\".\"commentable_type\" = 'Outlet'
INNER JOIN \"statistics\" 
ON \"statistics\".\"statable_id\" = \"outlets\".\"id\" 
AND \"statistics\".\"statable_type\" = 'Outlet' 
WHERE (\"outlets\".\"id\" = '1')

#=> [#<Outlet id: 1...>, #<Outlet id: 1...>]
# without the where I get back something like
# [...id: 1, id: 1, id: 5, id: 5, id: 5, id: 5 ]

我不知道怎么写,所以它只返回一个值(不只是使用distinct)。但这可能是我的下一个问题。

这是我正在尝试使用的 SQL。我也尝试过明确指定INNER 并颠倒等式的顺序:

SELECT \"followings\".* 
FROM \"followings\"
JOIN \"outlets\"
ON \"followings\".\"followable_id\" = \"outlets\".\"id\"
AND \"followings\".\"followable_type\" = 'Outlet'
JOIN \"people\"
ON \"followings\".\"followable_id\" = \"people\".\"id\"
AND \"followings\".\"followable_type\" = 'Person'
WHERE (\"followings\".\"user_id\" = '1')

#=> []
# Exact same result from removing the WHERE clause

每个连接都有记录。如果我单独加入任一表,它们都会返回我专门为测试 SQL 而创建的结果。所以:

SELECT \"followings\".* 
FROM \"followings\" 
INNER JOIN \"people\"
ON \"followings\".\"followable_id\" = \"people\".\"id\"
AND \"followings\".\"followable_type\" = 'Person' 
WHERE (\"followings\".\"user_id\" = '1')

#=> [<Following id: 2...>]
# And id: 1 for joining on outlets without people

这里让我难过的部分是工作版本和非工作版本本质上是相同的,但我不明白为什么它应该在一个地方工作而不是另一个地方

编辑:

进度,将followingsJOIN 更改为LEFT OUTER JOINs 将返回所需的结果。但是为什么它同时在 outlets.id = commentable_id= statable_id 工作?

而且,我刚刚尝试将outlets 也更改为 LOJ,在我见过的最长的 SQL 调用中,返回的结果列表大约是 outlets 表本身长度的两倍。所以,虽然这是一个进步,但我不认为这是一个通用的解决方案。

编辑 2:

感谢使用公认的答案进行测试,我意识到我选择的统计数据会给出“误导”的结果,因为每个出口都有一个统计数据。当我更改为更好的测试表(例如followings)时,JOIN 的行为相似。 UNION 方法返回预期的条目

【问题讨论】:

  • 对于第二个查询,followings.followable_type 不能同时是 = 'Outlet'= 'Person'。您的意思是使用outletspeople 进行这些比较吗?
  • 我想到了,但在我的工作示例中 outlets.id = commentable_id= statable_id 同时

标签: sql join


【解决方案1】:

我认为这应该可以满足您的需求。您可以分别获取这两个列表,然后将它们与UNION 结合起来。

SELECT followings.*
FROM followings
JOIN outlets ON followings.followable_id = outlets.id
WHERE followable_type = 'Outlet'

UNION

SELECT followings.*
FROM followings
JOIN people ON followings.followable_id = people.id
WHERE followable_type = 'Person'

【讨论】:

    【解决方案2】:

    您的问题查询,如下更改。将\"followings\".\"followable_type\" 设为OR 条件(已使用IN 运算符)。我也从 JOIN 到 WHERE 子句中删除了条件。

    SELECT \"followings\".* 
    FROM \"followings\"
    JOIN \"outlets\"
    ON \"followings\".\"followable_id\" = \"outlets\".\"id\"
    JOIN \"people\"
    ON \"followings\".\"followable_id\" = \"people\".\"id\"
    WHERE (\"followings\".\"user_id\" = '1')
    AND \"followings\".\"followable_type\" IN ('Outlet','Person')
    

    你也可以说

    WHERE (\"followings\".\"user_id\" = '1')
    AND (
    \"followings\".\"followable_type\" = 'Outlet'
     OR 
    \"followings\".\"followable_type\" = 'Person'
      )
    

    编辑:

    将条件添加到JOIN本身,然后不需要WHERE

    SELECT \"followings\".* 
    FROM \"followings\"
    JOIN \"outlets\"
    ON \"followings\".\"followable_id\" = \"outlets\".\"id\"
    AND \"followings\".\"followable_type\" IN ('Outlet','Person')
    AND (\"followings\".\"user_id\" = '1')
    JOIN \"people\"
    ON \"followings\".\"followable_id\" = \"people\".\"id\"
    

    【讨论】:

    • 所以,这确实返回一个条目,但不返回另一个。我很惊讶地看到。另外,如果使用JOINs 来完成,我会非常喜欢。
    • 它只返回Following id: 1,即joined 到people。出于某种原因,他们都忽略了第二个 joined 到 outlets。原版和修改版都是一样的。
    • @MCB,应该是吧?根据您的情况WHERE (\"followings\".\"user_id\" = '1')
    • @MCB,根据您的帖子,这对我来说是正确的;为了更进一步,我需要查看示例数据,但这完全是一个单独的问题。您可能希望发布一个包含示例数据和表 DDL 的单独线程。
    • 很抱歉@Rahul,但您的 SQL 不起作用。当它应该返回两个条目时,它只返回一个条目,并且没有一个回答我关于为什么给定的JOINs 行为不同的真正问题。如果 SQL 确实有效,如果没有其他人对我的问题给出更完整的答案,我可能会接受它,但不幸的是它都没有。
    猜你喜欢
    • 2012-03-05
    • 1970-01-01
    • 1970-01-01
    • 2019-07-13
    • 2013-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多