Postgres Join Query有时会采用笛卡尔积

时间:2015-05-12 06:50:47

标签: sql postgresql postgresql-9.3

我正在尝试为一个查询连接多个表,并且我从数据库得到不一致的结果,我相信我的查询是采用所有用户的笛卡尔积,当我只想要在DirectConversation中的用户。 / p>

架构供参考:

This is the schema for the tables in question, is it possible this is an error with my schema?

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

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" as c, "DirectMessage" as dm, "Profile" as u1, "Profile" as u2
WHERE u1."id_User" = c."id_User1"
AND u2."id_User" = c."id_User2"
AND c.id = dm."id_DirectConversation" 
AND 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;

预期结果(用户id = 1时的结果):

id | id_User1 | id_User2 | count | first_name | last_name |      company       |                                   picture                                   | first_name | last_name |    company     |                                 picture                                  
----+----------+----------+-------+------------+-----------+--------------------+-----------------------------------------------------------------------------+------------+-----------+----------------+--------------------------------------------------------------------------
  1 |        1 |        2 |     3 | Albert     | Einstein  | alberts inventions | http://upload.wikimedia.org/wikipedia/commons/d/d3/Albert_Einstein_Head.jpg | Nikola     | Tesla     | Teslas Widgets | http://upload.wikimedia.org/wikipedia/commons/7/79/Tesla_circa_1890.jpeg
(1 row)

(END)

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

id | id_User1 | id_User2 | count | first_name | last_name |      company       |                                                    picture                                                     | first_name | last_name |      company       |                                                    picture                                                     
----+----------+----------+-------+------------+-----------+--------------------+----------------------------------------------------------------------------------------------------------------+------------+-----------+--------------------+----------------------------------------------------------------------------------------------------------------
  1 |        1 |        2 |     4 | Albert     | Einstein  | alberts inventions | http://upload.wikimedia.org/wikipedia/commons/d/d3/Albert_Einstein_Head.jpg                                    | Albert     | Einstein  | alberts inventions | http://upload.wikimedia.org/wikipedia/commons/d/d3/Albert_Einstein_Head.jpg
  1 |        1 |        2 |     4 | Albert     | Einstein  | alberts inventions | http://upload.wikimedia.org/wikipedia/commons/d/d3/Albert_Einstein_Head.jpg                                    | Nikola     | Tesla     | Teslas Widgets     | http://upload.wikimedia.org/wikipedia/commons/7/79/Tesla_circa_1890.jpeg
  1 |        1 |        2 |     4 | Albert     | Einstein  | alberts inventions | http://upload.wikimedia.org/wikipedia/commons/d/d3/Albert_Einstein_Head.jpg                                    | Rosalind   | Franklin  | DNA R US           | http://upload.wikimedia.org/wikipedia/en/9/97/Rosalind_Franklin.jpg
  1 |        1 |        2 |     4 | Albert     | Einstein  | alberts inventions | http://upload.wikimedia.org/wikipedia/commons/d/d3/Albert_Einstein_Head.jpg                                    | Charles    | Babbage   | Babbages Cabbages  | http://upload.wikimedia.org/wikipedia/commons/6/6b/Charles_Babbage_-_1860.jpg

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

我正在使用的postgres版本:

版本

-----------------------------------------------------------------------------------------------------
 PostgreSQL 9.3.6 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2, 64-bit

1 个答案:

答案 0 :(得分:4)

我只是将你的联接的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子句分组为安全