2011-11-05 60 views
3

比方說,我有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

回答

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指出seqField可以%%physloc%%更換,如果你沒有一個現有的列使用。

+0

這將破壞順序,不應該嗎?如果(1,2)在(2,1)之前,我想要有結果(1,2)。如果(2,1)在(1,2)之前,那麼結果將是(2,1) – bliof

+0

如何做到這一點? – bliof

+0

@bliof - 我編輯了我的答案 - 看到一個正常運行的+測試的例子 – Hogan

0

你可以使用一個加盟找到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

0

我很確定你可以這樣做:

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

0

id1 + "|" + id2不同。例如這只是概念,我現在還沒有嘗試過,SELECT DISTINCT(CONCAT(id1,'|',id2)) FROM ...。 SEPH對組建議,由會更有意義,雖然

+0

不,這是錯誤的,你會得到1 | 2和2 | 1作爲截然不同 – Hogan

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並且不需要擔心添加列。

+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