37

{2,4,5,6,7} などの数字のリストがあります。{1,2,3,4,8,9} などの foos.ID を持つテーブル foos があります。

番号のリストを取得して、テーブルの ID フィールドに対応する番号がないものを見つけたいと思います。

これを実現する 1 つの方法は、ID フィールドに {2,4,5,6,7} をロードしたテーブル bars を作成することです。それなら、私はするだろう

バーを選択します。* バーから LEFT JOIN foos ON バー.ID = foos.ID WHERE foos.ID は NULL

ただし、このsans tempテーブルを実現したいと思います。

それがどのように起こるかについて誰にも意見がありますか?

4

5 に答える 5

38

これは非常に一般的な問題です。テーブルを作成せずにその場でリレーションを生成します。この問題のSQLソリューションはかなり厄介です。派生テーブルを使用した1つの例:

SELECT n.id
FROM
  (SELECT 2 AS id 
   UNION SELECT 3 
   UNION SELECT 4 
   UNION SELECT 5 
   UNION SELECT 6 
   UNION SELECT 7) AS n
  LEFT OUTER JOIN foos USING (id)
WHERE foos.id IS NULL;

ただし、6つではなく多くの値がある可能性があるため、これはあまり適切にスケーリングされません。UNION値ごとに1つ必要な長いリストを作成するのは面倒になる可能性があります。

もう1つの解決策は、10桁の汎用テーブルを手元に置いておき、それを複数の目的に繰り返し使用することです。

CREATE TABLE num (i int);
INSERT INTO num (i) VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);

SELECT n.id
FROM 
  (SELECT n1.i + n10.i*10 AS id
   FROM num AS n1 CROSS JOIN num AS n10
   WHERE n1.i + n10.i*10 IN (2, 3, 4, 5, 6, 7)) AS n
  LEFT OUTER JOIN foos USING (id)
WHERE foos.id IS NULL;

この場合は必要ありませんが、0..99から値を生成する内部クエリを示しています。ただし、リストに10より大きい値がある場合があります。重要なのは、1つのテーブルを使用すると、値ごとnumに1つの非常に長いチェーンに頼ることなく、多数を生成できるということUNIONです。また、必要な値のリストを1か所で指定できるため、より便利で読みやすくなります。

于 2008-11-07T21:31:46.373 に答える
21

一時テーブルを使用しない正確な問題の解決策は見つかりませんが、結合の代わりに副選択を使用してクエリを実行する別の方法は次のとおりです。

SELECT bars.* FROM bars WHERE bars.ID NOT IN (SELECT ID FROM foos)

私が最初に書いた他のポスターのように:

SELECT * FROM foos WHERE foos.ID NOT IN (2, 4, 5, 6, 7)

しかし、それから私はこれがあなたが望むものと反対のものを生み出していることに気づきました。

于 2008-11-07T21:11:54.447 に答える
6

PHP を使用している場合は、一時テーブルを作成せずにこれを機能させることができます。

SELECT ID FROM foos WHERE foos.ID IN (2, 4, 5, 6, 7)

PHP の array_diff() 関数を使用して、これを目的の結果に変換できます。リスト (2,4,5,6,7) が $list という配列にあり、上記のクエリの結果が配列 $result にある場合、

$no_counterparts = array_diff($list, $result);

...リスト内のすべての数値を返しますが、データベース テーブルには対応するものはありません。このソリューションは、クエリ内ですべての操作を実行するわけではありませんが、PHP で行う必要がある後処理は、必要なものを取得するために最小限であり、一時テーブルを作成する必要がないようにする価値がある場合があります。

于 2011-05-04T23:36:47.840 に答える
1

私も同様の問題を抱えていました。自動インクリメントの主キーにいくつかの欠落した値がある範囲があったので、最初に、いくつあるかを見つけました select count(*) from node where nid > 1962。この数値を最大値と比較すると、数値が欠落しています。次に、このクエリを実行しました。 select n2.nid from node n1 right join node n2 on n1.nid = (n2.nid - 1) where n1.nid is null and n2.nid > 1962 これにより、連続していない欠落レコードの数が検出されます。連続したものは表示されません。また、ON句を変更して緯度を大きくする(JOINテーブルを大幅に大きくする)以外に、その方法が完全にはわかりません。いずれにせよ、これにより、合計7つの欠落のうち5つの結果が得られ、他の2つは5つのうち少なくとも1つに隣接することが保証されました。欠落している数が多い場合は、残りの欠落を見つける他の方法が必要になる可能性があります。

于 2010-04-21T14:02:30.567 に答える
0

Alnitak(およびあなたの)ソリューションは機能するはずですが、SQL言語でのみ機能する他のソリューションについては何もできません。

しかし、ここに問題があります-値のリストをどのように渡すのですか?これを呼び出し元のコードで処理する方がよいのではないでしょうか。つまり、IDを要求し、この種の操作により適した言語である可能性のある照合コードで比較します。

于 2008-11-07T21:30:41.490 に答える