In SQLite I have a table that is created like this (simplified):
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);
Now I want to list combinations that match each other. Consider column local as local bank account and remote as remote bank account. Whenever a transaction is made from local to remote with value x and there exists a matching transaction which received the value x but as negative value (in relation to the first found), I want to have an output from SQLite.
My current approach is like this:
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)"
But this returns:
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
What I wanted as result would be this:
id|local|remote|value|id|local|remote|value
1|a|b|1|2|b|a|-1
4|a|d|2|6|d|a|-2
Lines which don’t have a matching partner should not be displayed – every line could only match to at most one other transaction. I tried with GROUP BY, but this didn’t work with q1.id and q2.id as parameter.
As there might be several rows with the same values for local/remote/value,
the rank of the rows within each such set has to be calculated in order to pair the rows correctly.
This is easier using other databases than sqlite (using row numbering primitives, CTEs etc), but in sqlite the correct result may be obtained like this:
See http://sqlfiddle.com/#!5/c684e/66/0