Sql Postgres连接查询有时采用笛卡尔积

Sql Postgres连接查询有时采用笛卡尔积,sql,postgresql,postgresql-9.3,Sql,Postgresql,Postgresql 9.3,我试图为一个查询连接多个表,但从数据库中得到的结果不一致,我相信我的查询是所有用户的笛卡尔乘积,而我只需要DirectConversation中的用户 供参考的模式: 查询是(其中$id代表变量User.id): 选择c.*,计数(dm.id), u1.名字,u1.姓氏,u1.公司,u1.图片, u2.名字,u2.姓氏,u2.公司,u2.图片 从“DirectConversation”作为c,“DirectMessage”作为dm,“Profile”作为u1,“Profile”作为u2 其中u

我试图为一个查询连接多个表,但从数据库中得到的结果不一致,我相信我的查询是所有用户的笛卡尔乘积,而我只需要DirectConversation中的用户

供参考的模式:

查询是(其中$id代表变量User.id):

选择c.*,计数(dm.id),
u1.名字,u1.姓氏,u1.公司,u1.图片,
u2.名字,u2.姓氏,u2.公司,u2.图片
从“DirectConversation”作为c,“DirectMessage”作为dm,“Profile”作为u1,“Profile”作为u2
其中u1.“id\u User”=c“id\u User1”
u2.“id_User”=c.“id_User2”
c.id=dm.“id\u DirectConversation”
和dm.viewed='f'和dm.deleted='f'
和c.“id_User1”=$id或c.“id_User2”=$id
按c.id、u1.id、u2.id分组;
预期结果(用户id=1时的结果):

错误结果(用户id=2时的结果):

。。。请注意,为了简洁起见,这被截断了。我相信这是采取笛卡尔产品的所有用户,但我不知道为什么

我正在使用的postgres版本:

版本
我刚刚将连接的where子句移动到ON语句中,并进行了适当的连接,如果这不起作用,我将设置一个sqlfiddle,看看这个sql有什么问题

SELECT c.*, count(dm.id), 
    u1.first_name, u1.last_name, u1.company, u1.picture, 
    u2.first_name, u2.last_name, u2.company, u2.picture
    FROM "DirectConversation" c
    JOIN "DirectMessage" dm ON c.id = dm."id_DirectConversation" 
    JOIN "Profile" u1 ON u1."id_User" = c."id_User1"
    JOIN "Profile" u2 ON u2."id_User" = c."id_User2"
    WHERE 
    dm.viewed = 'f' AND dm.deleted = 'f'
    AND (c."id_User1" = $id OR c."id_User2" = $id)
    GROUP BY c.id, u1.id, u2.id;

编辑:为了安全起见,将OR子句分组

我刚刚将连接的where子句移动到ON语句中,并进行了正确的连接,如果这不起作用,我将设置一个SQLFIDLE,看看这个sql有什么问题

SELECT c.*, count(dm.id), 
    u1.first_name, u1.last_name, u1.company, u1.picture, 
    u2.first_name, u2.last_name, u2.company, u2.picture
    FROM "DirectConversation" c
    JOIN "DirectMessage" dm ON c.id = dm."id_DirectConversation" 
    JOIN "Profile" u1 ON u1."id_User" = c."id_User1"
    JOIN "Profile" u2 ON u2."id_User" = c."id_User2"
    WHERE 
    dm.viewed = 'f' AND dm.deleted = 'f'
    AND (c."id_User1" = $id OR c."id_User2" = $id)
    GROUP BY c.id, u1.id, u2.id;

编辑:为了安全起见,将OR子句分组

,因为您没有正确创建join语句使用join语句连接表,而不仅仅是逗号,并使用ON语句说明哪些值需要相同,不是where子句,因为您没有正确创建join语句使用join语句来连接表,而不仅仅是逗号,并使用ON语句来说明哪些值需要相同,而不是where子句。谢谢Jeremy。我原以为我可以用更简单的符号来表示,但你是对的,在这里使用正确的联接是一种方法。它解决了你的问题吗?是的,当使用id=2时,不再有所有用户的笛卡尔积。因此,我相信您的评估是正确的,即join语句的格式不正确。好吧,很高兴我能提供帮助,试着养成写join的习惯,如果你不这样做,你永远不知道你会得到什么:D@Blakedallen:组合
条件而不使用括号通常是一个等待发生的错误。我想你真的想要:
和(c.“id\u User1”=$id或c.“id\u User2”=$id)
看起来很棒,谢谢Jeremy。我原以为我可以用更简单的符号来表示,但你是对的,在这里使用正确的联接是一种方法。它解决了你的问题吗?是的,当使用id=2时,不再有所有用户的笛卡尔积。因此,我相信您的评估是正确的,即join语句的格式不正确。好吧,很高兴我能提供帮助,试着养成写join的习惯,如果你不这样做,你永远不知道你会得到什么:D@Blakedallen:组合
条件而不使用括号通常是一个等待发生的错误。我想你实际上想要:
和(c.“id\u User1”=$id或c.“id\u User2”=$id)
-----------------------------------------------------------------------------------------------------
 PostgreSQL 9.3.6 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2, 64-bit
SELECT c.*, count(dm.id), 
    u1.first_name, u1.last_name, u1.company, u1.picture, 
    u2.first_name, u2.last_name, u2.company, u2.picture
    FROM "DirectConversation" c
    JOIN "DirectMessage" dm ON c.id = dm."id_DirectConversation" 
    JOIN "Profile" u1 ON u1."id_User" = c."id_User1"
    JOIN "Profile" u2 ON u2."id_User" = c."id_User2"
    WHERE 
    dm.viewed = 'f' AND dm.deleted = 'f'
    AND (c."id_User1" = $id OR c."id_User2" = $id)
    GROUP BY c.id, u1.id, u2.id;