2012-11-15 36 views
1

SQLite中我有一個像這樣(簡化)創建的表:如何找出哪些行匹配,而不是每行有多個結果?

CREATE TABLE [entries] (
    [id]  INTEGER NOT NULL PRIMARY KEY, 
    [local] VARCHAR, 
    [remote] VARCHAR, 
    [value] INTEGER 
); 

INSERT INTO entries (local, remote, value) VALUES ("a", "b", 1); 
INSERT INTO entries (local, remote, value) VALUES ("b", "a", -1); 
INSERT INTO entries (local, remote, value) VALUES ("b", "a", -1); 

INSERT INTO entries (local, remote, value) VALUES ("a", "d", 2); 
INSERT INTO entries (local, remote, value) VALUES ("a", "d", 2); 
INSERT INTO entries (local, remote, value) VALUES ("d", "a", -2); 

現在我想列出相互匹配該組合。考慮將列的本地作爲本地銀行帳戶,並將遠程作爲遠程銀行帳戶。每當一個事務從本地遠程與值X製成,並且存在其接收的值X但作爲負值(相對於找到的第一個)相匹配的事務,我想有一個輸出來自SQLite。

我目前的做法是這樣的:

sqlite3 -header demo.db \ 
    "SELECT * FROM 
     (SELECT * FROM entries) AS q1, 
     (SELECT * FROM entries) AS q2 

    WHERE q1.local = q2.remote AND 
      q1.remote = q2.local AND 
      q1.value = (q2.value * -1)" 

但這返回:

id|local|remote|value|id|local|remote|value 
1|a|b|1|2|b|a|-1 
1|a|b|1|3|b|a|-1 
2|b|a|-1|1|a|b|1 
3|b|a|-1|1|a|b|1 
4|a|d|2|6|d|a|-2 
5|a|d|2|6|d|a|-2 
6|d|a|-2|4|a|d|2 
6|d|a|-2|5|a|d|2 

我想要什麼作爲的結果會是這樣:

id|local|remote|value|id|local|remote|value 
1|a|b|1|2|b|a|-1 
4|a|d|2|6|d|a|-2 

該行不不應該顯示匹配的合作伙伴 - 每行只能匹配至多一個其他事務。我試着用GROUP BY,但是這並不適用於q1.idq2.id作爲參數。

+0

好,當兩行相同(除了它們的ID)時,如何決定使用哪一行? – NullUserException

+0

第一個結果是好的,稍後會有一個額外的日期檢查(+/- 3天),但即使在那裏,第一個就足夠了。 – Sven

+0

這似乎過於複雜,沒有理由。難道你不能只添加一個像'origin_id'這樣的列,這樣你就可以確切知道哪一個是原始ID?這需要很多猜測,並使其更簡單。 – NullUserException

回答

2

由於本地/遠程/值可能有多行具有相同的值,因此必須計算每個此類集內的行的排名,以便正確配對行。

該使用其他數據庫比SQLite是容易(使用行編號元,熱膨脹係數等),但SQLite中正確的結果可能是這樣獲得的:

SELECT t1.id, t1.local, t1.remote, t1.value, 
t2.id, t2.local, t2.remote, t2.value FROM 
(SELECT q1.*, count(q1b.id) AS rank 
FROM entries q1 LEFT JOIN entries q1b 
ON q1.local = q1b.local AND q1.remote = q1b.remote 
AND q1.value = q1b.value AND q1.id >= q1b.id 
GROUP BY q1.id) AS t1, 
(SELECT q2.*, count(q2b.id) AS rank 
FROM entries q2 LEFT JOIN entries q2b 
ON q2.local = q2b.local AND q2.remote = q2b.remote 
AND q2.value = q2b.value AND q2.id >= q2b.id 
GROUP BY q2.id) AS t2 
WHERE t1.local = t2.remote AND t1.remote = t2.local 
AND t1.value = - t2.value 
AND t1.id < t2.id AND t1.rank = t2.rank 

http://sqlfiddle.com/#!5/c684e/66/0

+0

謝謝,用[SQL Fiddle](http://sqlfiddle.com/#!5/c684e/26)(感謝@NullUserException)對它進行了測試,但它不適用於示例數據(左窗口),其中預期的結果是(q1.id到q2.id):1-3,2-4,5-6。 – Sven

+0

@Sven See更新了答案。 –

+0

哇,非常複雜,但似乎工作 - 謝謝你! – Sven

0
SELECT * 
FROM (SELECT MIN(id) AS id, local, remote, value 
     FROM entries 
     GROUP BY local, remote, value 
    ) AS e1, 
    (SELECT MIN(id) AS id, local, remote, value 
     FROM entries 
     GROUP BY local, remote, value 
    ) AS e2 
WHERE e1.local = e2.remote 
    AND e1.remote = e2.local 
    AND e1.value = -e2.value 
    AND e1.id < e2.id 
+0

謝謝,但請參閱[SQL小提琴](http://sqlfiddle.com/#!5/c684e/48)查看只顯示第一個匹配對。只有:1-3,5-6,但缺少2-4。 – Sven

相關問題