SQL-使用同一表进行左连接,使用ON语句匹配左右表时出现问题

时间:2019-03-08 14:33:06

标签: sql postgresql

我是SQL新手。考虑下表(table1)

s_id    v_id
1       1
2       1
2       2
2       3
2       5
2       6
2       7
3       1
3       2
3       6
3       7
3       8
4       1
and so on

在这里,请仅考虑s_id 2和3。我希望s_id = 2的记录在s_id = 3(v_id 3和5)中不可用。不用担心s_id = 3(v_id 8)中的新ID

我需要的输出

s_id    v_id
2       3
2       5

我尝试了以下查询,但返回的查询与我的查询相反。

SELECT a.* 
  from table1 a 
  LEFT 
  JOIN table1 b 
    ON a.v_id = b.v_id 
 WHERE a.s_id = 2 
   AND b.s_id = 3

在这里,我知道ON语句中的条件是错误的。 应该是这样

a.v_id is not in b.v_id 

在这里,我不想进行子查询。 欢迎加入或进行简单查询。

4 个答案:

答案 0 :(得分:3)

https://www.db-fiddle.com/f/6H4ubXubMgJuoadXuxHbv4/0

SELECT t1.*
FROM t1
WHERE s_id = 2
  AND v_id NOT IN (
      SELECT v_id 
      FROM t1
      WHERE s_id = 3
      )

或者您也可以将JOIN查询转换为:

https://www.db-fiddle.com/f/vCVDCV9sCu7F8QoFiU5in9/1

SELECT a.* from table1 a 
LEFT JOIN table1 b 
ON a.v_id = b.v_id
   AND b.s_id=3
WHERE a.s_id=2 
   AND b.v_id IS NULL

答案 1 :(得分:2)

另一种汇总查询,可能不太可能动脑筋:

SELECT max(s_id) AS s_id, v_id
FROM   tbl
WHERE  s_id in (2, 3)
GROUP  BY v_id
HAVING max(s_id) = 2;

db <>提琴here

(而且,重复max(s_id)应该会便宜一些。)

列出所有找到v_id的{​​{1}}(1次或多次),但不列出更大的s_id = 2

答案 2 :(得分:1)

一种有趣的替代方法是使用聚合:

select max(s_id) as s_id, v_id
from t
where s_id in (2, 3)
group by v_id
having not bool_or(s_id = 3)

或等效地:

having bool_and(s_id = 3)

Here是数据库提琴。

答案 3 :(得分:1)

如果您要查找的解决方案将始终比较2和3,或3和4,或5和6(或第一个数字及其上方的数字),则您可能会对其使用左连接b.s_id-第二个表为1,并且仅在第二个表的b.s_id值为null的情况下。

您正在此处查找的部分(如果要避免子查询)也在v_id上加入,然后过滤到WHERE b.v_id IS NULL。

如果只关心a.s_id = 2,请在WHERE子句中指定。使用JOIN可以使数据正确结合在一起。

`SELECT a.* 
  from table1 a 
  LEFT 
  JOIN table1 b 
    ON a.s_id = b.s_id -1
   AND a.v_id = b.v_id
 WHERE b.v_id IS NULL
   AND a.s_id = 2`