如何用except除掉2个查询

时间:2014-03-27 08:18:01

标签: sql postgresql except

我有两个问题:

SELECT 
      users.id, 
      users.gender, 
      users.status, 
      users.icon_id, 
      users.image_name, 
      coords.lat, 
      coords.lng, 
      users.mess_count 
FROM 
    users 
INNER JOIN 
    coords ON users.id = coords.user_id

然后我选择被阻止的用户:

SELECT 
      first_user, 
      second_user 
FROM 
    blocks 
WHERE 
    first_user = $1 OR second_user = $1

从第一张桌子我需要选择所有具有坐标但未被阻止的用户,我还需要一些公共信息(性别等)。然后因为我需要两个侧面阻挡。我必须选择是用户阻止了他,或者他被该用户阻止了。所以$ 1是当前用户,我在block表中选择是我的id,如果是 - 我从第一次查询中排除了另一个用户。

然后在我的编程语言中使用字符串操作,我转换我的字符串以排除从第二次查询得到的结果。

我可能可以用EXCEPT来做,但是我不能这样做,因为我只有第二个查询选择了2列,我需要更多,最终结果:users.id, users.gender, users.status, users.icon_id, users.image_name, coords.lat, coords.lng, users.mess_count

3 个答案:

答案 0 :(得分:1)

您可以与blocks表保持联接,然后使用is null检查。

SELECT 
      users.id, 
      users.gender, 
      users.status, 
      users.icon_id, 
      users.image_name, 
      coords.lat, 
      coords.lng, 
      users.mess_count 
FROM 
      users 
INNER JOIN coords ON users.id=coords.user_id
LEFT JOIN blocks ON users.id = blocks.first_user OR users.id = blocks.second_user
WHERE blocks.first_user IS NULL

答案 1 :(得分:1)

有几种方法可以做到这一点,唯一明显妥协的因素是我相信你想要排除出现在{{> 中的{{em> 1}}表。

SQL传统上使用blocks逻辑具有较弱的性能,以下查询尝试解决此问题。 (部分原因是它能够更好地利用索引)

OR


根据PostgreSQL的版本,优化器可能对相关子查询效率较低,例如我上面使用的那些。在这种情况下,以下可能仍然更具性能。 (它仍然避免使用 OR 。)

SELECT 
  users.id, 
  users.gender, 
  users.status, 
  users.icon_id, 
  users.image_name, 
  coords.lat, 
  coords.lng, 
  users.mess_count 
FROM 
  users 
INNER JOIN
  coords
    ON users.id=coords.user_id
WHERE
      NOT EXISTS (SELECT * FROM blocks WHERE first_user  = users.id AND second_user = $1)
  AND NOT EXISTS (SELECT * FROM blocks WHERE second_user = users.id AND first_user  = $1)

答案 2 :(得分:1)

检查一下,我使用NOT IN编写了查询。

SELECT 
  users.id, 
  users.gender, 
  users.status, 
  users.icon_id, 
  users.image_name, 
  coords.lat, 
  coords.lng, 
  users.mess_count 
FROM 
  users 
  INNER JOIN coords ON users.id=coords.user_id
  Where 
   users.id NOT IN (SELECT first_user FROM blocks WHERE first_user=$1)
   AND
   users.id NOT IN (SELECT second_user FROM blocks WHERE second_user=$1)