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

一致するパートナーがない行は表示しないでください。すべての行は、最大で1つの他のトランザクションにしか一致できません。GROUP BYを試してみましたが、 q1.idq2.idをパラメーターとして使用できませんでした。

4

2 に答える 2

2

ローカル/リモート/値に同じ値を持つ複数の行が存在する可能性があるため、行を正しくペアリングするには、そのような各セット内の行のランクを計算する必要があります。

これは、sqlite以外のデータベース(行番号付けプリミティブ、CTEなどを使用)を使用する方が簡単ですが、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を参照してください

于 2012-11-15T17:48:36.337 に答える
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
于 2012-11-15T18:45:20.710 に答える