如果我同时拥有(A,B)和(B,A),则只选择一对

时间:2016-06-28 11:40:07

标签: sql sql-server select

这是一个简单的问题,当我有(A,B)作为我的查询的结果时,我想只有(A,B),而不是(B,A)。

例如,我的查询返回:

161, 52 
161, 53
53, 161
53, 161

这是我的问题:

SELECT S1.SURVEY_ID, S2.SURVEY_ID

  FROM SURVEYS S1, SURVEYS S2

  WHERE (S2.START_DATE BETWEEN S1.START_DATE and S1.END_DATE
  OR S2.END_DATE BETWEEN S1.START_DATE and S1.END_DATE)
  AND S1.SURVEY_ID != S2.SURVEY_ID

ORDER BY S1.SURVEY_ID, S2.SURVEY_ID

3 个答案:

答案 0 :(得分:4)

您可以使用条件排序将每个集(A,B) , (B,A)组合为一个组。

SELECT MAX(S1.SURVEY_ID) as survey_id_1, MIN(S2.SURVEY_ID) as survey_id_2
FROM SURVEYS S1
INNER JOIN SURVEYS S2
 ON (S2.START_DATE BETWEEN S1.START_DATE and S1.END_DATE
     OR S2.END_DATE BETWEEN S1.START_DATE and S1.END_DATE)
WHERE S1.SURVEY_ID != S2.SURVEY_ID
GROUP BY CASE WHEN S1.SURVEY_ID > S2.SURVEY_ID
              THEN S1.SURVEY_ID
              ELSE S2.SURVEY_ID
         END
ORDER BY survey_id_1, survey_id_2

这将导致(更大的调查,更小的调查) - 每组1个。

我还将您的连接语法更改为正确的连接语法,请尽量避免使用隐式连接语法(以逗号分隔)。

答案 1 :(得分:2)

这是一种方法:

WITH SS as (
      SELECT S1.SURVEY_ID as SURVEY_ID1, S2.SURVEY_ID as SURVEY_ID2
      FROM SURVEYS S1 JOIN
           SURVEYS S2
           ON (S2.START_DATE BETWEEN S1.START_DATE and S1.END_DATE OR
               S2.END_DATE BETWEEN S1.START_DATE and S1.END_DATE
              ) AND
              S1.SURVEY_ID <> S2.SURVEY_ID
     )
SELECT ss.*
FROM ss
WHERE SURVEY_ID1 < SURVEY_ID2
UNION ALL
SELECT ss.*
FROM ss
WHERE SURVEY_ID1 > SURVEY_ID2 AND
      NOT EXISTS (SELECT 1 FROM ss ss2 WHERE ss2.SURVEY_ID1 = ss.SURVEY_ID2 AND ss2.SURVEY_ID2 = ss.SURVEY_ID1);

但是,如果您只是想要重叠调查,那么这将是适当的查询:

      SELECT S1.SURVEY_ID as SURVEY_ID1, S2.SURVEY_ID as SURVEY_ID2
      FROM SURVEYS S1 JOIN
           SURVEYS S2
           ON S2.START_DATE <= S1.END_DATE AND
              S2.END_DATE >= S1.START_DATE 
              S1.SURVEY_ID < S2.SURVEY_ID;

答案 2 :(得分:2)

不确定我是否真的理解这个问题。猜猜:你希望(A,B)被视为(B,A)的副本,其中一个被删除。

将值放入一个订单(在降低之前更高),然后您可以使用distinct:

SELECT distinct 
  (CASE WHEN S1.SURVEY_ID > S2.SURVEY_ID THEN S1.SURVEY_ID ELSE S2.SURVEY_ID END) as "higher id",
  (CASE WHEN S1.SURVEY_ID > S2.SURVEY_ID THEN S2.SURVEY_ID ELSE S1.SURVEY_ID END) as "lower id"
...