将表连接到自身并选择不匹配的值

时间:2013-11-05 01:04:11

标签: mysql sql join

我希望获得data的1-3中不在id的所有id> 6

我使用id来简化,但我真的使用时间戳。

CREATE TABLE test (
  id bigint(20) NOT NULL AUTO_INCREMENT,
  data varchar(3) NOT NULL,
  PRIMARY KEY (id)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;

INSERT INTO test (id, data) VALUES
(1, 'abc'),
(2, 'def'),
(3, 'ghi'),
(4, 'jkl'),
(5, 'mno'),
(6, 'pqr'),
(7, 'def'),
(8, 'vxw'),
(9, 'yz');

对我尝试的几十个问题进行了一次查询。

SELECT
  t1.data t1_data,
  t2.data t2_data
FROM test t1
JOIN test t2
  ON t2.id BETWEEN 1 AND 3
    AND t1.id > 6
    AND t1.data <> t2.data

所以我想得到这个结果:

+----------+
|   data   |
+----------+
|   abc    |
|   ghi    |
+----------+

4 个答案:

答案 0 :(得分:1)

SELECT t1.data AS t1_data
FROM test t1
WHERE t1.id BETWEEN 1 AND 3
AND NOT EXISTS(
  SELECT *
  FROM test t2 
  WHERE t2.data = t1.data
  AND  t2.id > 6
  );

答案 1 :(得分:1)

这是set-within-sets子查询的示例。我喜欢使用having子句聚合来处理这些,因为这是最常用的方法。在你的情况下:

select t1.data 
from test t1
group by t.data
having sum(id between 1 and 3) > 0 and
       sum(id > 6) = 0;

having子句中的条件计算满足每个条件的行数。第一个表示至少有一行(对于给定的data),id介于1和3之间。第二行表示没有id大于6的行

答案 2 :(得分:0)

您可以使用NOT EXISTS子句:

SELECT DISTINCT t1.data
FROM test t1
WHERE t1.id BETWEEN 1 AND 3
AND NOT EXISTS
(
    SELECT 1
    FROM test t2
    WHERE t2.data = t1.data
    AND t2.id > 6
);

我在这里使用DISTINCT因为我认为例如data值为id=2data值为id=3 。必要时将其删除。

答案 3 :(得分:0)

有几种方法可以做到(可能性能方面,外部联接可能是最好的)但概念上就是这样:

SELECT t1.data
  FROM test t1
 WHERE t1.id < 4 
   AND t1.data NOT IN
   (SELECT t2.data
      FROM test t2
     WHERE t2.id > 6)

外部联接版本如下所示:

SELECT t1.data
  FROM test t1 LEFT OUTER JOIN test t2
    ON t1.data = t2.data and t1.id < 4 and t2.id > 6
 WHERE t2.id IS NULL