SQL选择的不同的2列对

问题描述:

比方说,我有2列:SQL选择的不同的2列对

_______________ 
| 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 
+1

你想达到的结果集是什么?这个问题并不清楚。 – aleroot

+2

你是什么意思的“每个”的顶部? – pinaldesai

+0

我已经更新了这个问题 – bliof

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

在这个例子中,我假设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指出seqField可以%%physloc%%更换,如果你没有一个现有的列使用。

+0

这将破坏顺序,不应该吗?如果(1,2)在(2,1)之前,我想要有结果(1,2)。如果(2,1)在(1,2)之前,那么结果将是(2,1) – bliof

+0

如何做到这一点? – bliof

+0

@bliof - 我编辑了我的答案 - 看到一个正常运行的+测试的例子 – Hogan

你可以使用一个加盟找到id1, id2匹配的对倒:

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

过滤器不起作用 - 他想知道过滤的是什么 - 列表只给他一次这些值。 – Hogan

+0

@霍根:你是对的,完全误读了这个问题,重写了答案:) – Andomar

+0

当我测试它时,这仍然不起作用。 – Hogan

我很确定你可以这样做:

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

确定,从显示出来让过去的(1,2)和(1,2):

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 
+0

这将返回(1,2)和(2,1) – Hogan

+0

我解决了我的答案来解决这个问题。 – Seph

+0

你试过了吗? – Seph

id1 + "|" + id2不同。例如这只是概念,我现在还没有尝试过,SELECT DISTINCT(CONCAT(id1,'|',id2)) FROM ...。 SEPH对组建议,由会更有意义,虽然

+0

不,这是错误的,你会得到1 | 2和2 | 1作为截然不同 – Hogan

在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并且不需要担心添加列。

+0

我看到这不会返回多个(1,2 )但不会返回(1,2)和(2,1)? – Hogan

+0

我测试了你的代码,它确实返回了两个 - 查看我的答案。 – Hogan

+0

啊 - 我的道歉,先读 - 这是我认为你需要的。 尝试此SELECT a.col1,a.col2 FROM回答一个 WHERE EXISTS(SELECT 1 FROM应答b WHERE b.col1 = a.col2 AND b.col2 = a.col1 和A。%% physloc %% sqlchan