sql选择2列对的不同

时间:2011-11-05 11:16:51

标签: sql sqlite

假设我有两列:

_______________
| id1  |  id2 |
|------|------|
|  1   |   2  |
|  2   |   1  |
|  3   |   4  |
|  4   |   1  |
|  4   |   3  |
|  1   |   4  |
      ...

如果我有一行id1 = 1且id2 = 2,那么在它之后会有一行,即id1 = 2和id2 = 1.

如何获得每个(id1,id2)对的顶部?


更新

示例的结果应为:

row1: 1 | 2
row2: 3 | 4
row3: 4 | 1

5 个答案:

答案 0 :(得分:2)

链接回原始表很大程度上取决于该表中导致订单的内容。让我们说你有一个日期字段或一个序列字段,你想要最小的值......

在这个例子中,我假设seqField按行

是唯一的

然后它看起来像这样:

--drop table #test

 SELECT 1 as seqField, 1 as id1, 2 as id2
 INTO #test
 UNION ALL
 SELECT 2,2,1
 UNION ALL
 SELECT 3,3,4
 UNION ALL
 SELECT 4,4,1
 UNION ALL
 SELECT 5,4,3
 UNION ALL
 SELECT 6,1,4 
 UNION ALL
 SELECT 7,10,20;

WITH norm AS 
( 
   SELECT CASE WHEN id1 > id2 THEN id1 ELSE id2 END as a,
          CASE WHEN id1 < id2 THEN id1 ELSE id2 END as b, * 
   FROM #test
), setList AS
(
  SELECT DISTINCT a, b, min(seqField) as s
  FROM norm
  GROUP BY a, b
)
SELECT #test.* 
FROM #test
JOIN setList ON #test.seqField = setList.s

这给出了

seq id1 id2
1   1   2
3   3   4
4   4   1
7   10  20

正如sqlchan指出的那样,如果您没有要使用的现有列,则可以用%%physloc%%替换seqField。

答案 1 :(得分:0)

您可以使用联接来查找与id1, id2倒置的匹配对:

select  t2.*
from    YourTable t1
join    YourTable t2
on      t2.id1 = t1.id2
        and t2.id2 = t1.id1

答案 2 :(得分:0)

我很确定你可以做到:

SELECT `id1`, `id2`
FROM `table` 
GROUP BY `id1`, `id2`
ORDER BY `id1`, `id2`

好的,从(1,2)和(2,1)显示出来:

SELECT `id1`, `id2`
FROM `table`  a
WHERE NOT EXISTS (
    SELECT TOP 1 1 
    FROM `table` b 
    WHERE b.`id1` < b.`id2` AND b.`id1` = a.`id2` AND b.`id2` = a.`id1'
)
ORDER BY `id1`, `id2`

如果您想实际保留订单以便显示第一行,那么您需要使用ROWID(更多信息:http://www.sqlite.org/autoinc.html

SELECT id1, id2
FROM `table`  a
WHERE NOT EXISTS (
    SELECT TOP 1 1 
    FROM `table` b 
    WHERE b.ROWID < a.ROWID AND b.id1 = a.id2 AND b.id2 = a.id1
)

结果:

row1: 1 | 2
row2: 3 | 4
row3: 4 | 1

答案 3 :(得分:0)

id1 + "|" + id2上采用不同的方式。例如这只是概念,我现在还没有尝试过,SELECT DISTINCT(CONCAT(id1,'|',id2)) FROM ...。 Seph对group by的推荐会更有意义

答案 4 :(得分:0)

在SQL Server 2008中......

SELECT a.col1,a.col2
FROM answer a 
JOIN answer b ON a.col1 = b.col2 and b.col1 = a.col2
and a.%%physloc%% = (SELECT MIN(c.%%physloc%%) 
                     FROM  answer c WHERE c.col1 = a.col1 and c.col2 = a.col2)
and b.%%physloc%% = (SELECT MIN(c.%%physloc%%) 
                     FROM answer c WHERE c.col1 = b.col1 and c.col2 = b.col2)
ORDER BY CASE 
     WHEN a.col1 > a.col2 
     THEN a.col2 
     ELSE b.col2 
     END

但是我不会使用%% physloc %%(太internalesque) - 如果顺序很重要,我会引入一个rowid标识列。 对于Oracle,您可以使用ROWID,而不必担心添加列。