0

基本的に列を持つ、さまざまなソースからの結果を含む mysql テーブルがあります。

id     (PRIMARY KEY)
source (INT)
value  (VARCHAR)
score  (FLOAT)

id source value score
-- ------ ----- -----
1    1     dog   0.2
2    1     cat   2.5
3    1     pig   4.0
4    2     dog   2.3
5    2     dog   1.5
6    2     cat   1.4
7    2     hen   0.7

or (ここで + は結合を意味します)などの sourcesに対してセット操作を実行する必要がありますが、をキーとして使用し、完全な行を返します。式を select ステートメントに変換しています (ネストされた各部分式が select になります)。これらは Web 経由のリクエストであるため、パフォーマンスが懸念されますが、一方で、最初のリクエストの後に結果をキャッシュします。1 ∩ 2 ∩ 3(1 + 2 + 3) ∩ (4 + 5 + 6)

1 ∩ 2例として、値に基づいて 2 つのソースの交差部分にある行をクエリする方法を見てみましょう。で値を取得できます

SELECT value
FROM table
WHERE source=1 OR source=2
GROUP BY value HAVING COUNT (DISTINCT source) = 2

そして、私は行を取り戻すことさえできます

SELECT table.id, table.value, table.source
FROM (
    SELECT value
    FROM table
    WHERE source=1 OR source=2
    GROUP BY value HAVING COUNT (DISTINCT source) = 2) AS intersection
JOIN table ON intersection.value = table.value
WHERE table.source=1 or table.source=2

降伏

id source value score
-- ------ ----- -----
1    1     dog   0.2
2    1     cat   2.5
4    2     dog   2.3
5    2     dog   1.5
6    2     cat   1.4

ただし、元のテーブルに戻ってソースに基づいて再度制限するため、処理する必要があるネストされた式に対してすぐに使用できるソリューションではありません。代わりに、各 select ステートメントがデータ テーブルのサブセットを生成する 2 つの select の結果の共通部分を見つけることを検討してください。テーブル全体に参加できなくなりました。2 つの選択の結合との交差点に参加する必要がありますが、それはまったくスケーラブルではないようです。

私が考えた別の方法は、IDでGROUP_CONCATを使用してから、IDのリストを行に分割することでした(ストアドプロシージャまたはPythonのいずれかで)。そのストアド プロシージャを見て、代わりに、クエリ全体に対して独自のプロシージャを作成する必要があるのではないかと考えました。

バニラ SQL でこれらのクエリを実行する別の方法はありますか? そうでない場合は、ストアド プロシージャを作成してみます (これまでやったことがないので、楽しいはずです)。ここでストアド プロシージャを使用するのが最善の方法ですか?また、最初のソリューション (一時テーブルと結合)、2 番目のソリューション (group_concat と分割)、または 3 番目のソリューションを完全に使用することに関する推奨事項はありますか? ストアド プロシージャについて十分な知識がなく、どの程度細分化できるかを知ることができません。

4

1 に答える 1

0

このステートメント「具体的には、値に基づいて 2 つのソースが交差する行をクエリするにはどうすればよいですか?」に基づいて、1 つ以上のソースを指定し、一致する値を持つすべての行を返したいようです。

select *
from t
where t.source in (select 1 as source union all select 2 as source) and
      t.value in (select value
                  from (select 1 as source union all select 2 as source) sources join
                       t
                       on t.source = sources.source
                  group by value
                  having count(distinct t.source) = 2
                 )

このバージョンでは、ソースのリストを 2 回 (サブクエリで 1 回、外側のクエリで 1 回) 入力し、数値 "2" をハードコーディングする必要があります。他のデータベースでは、"with" 句を使用して、クエリ全体で再利用できるエイリアスとしてリストを定義するのは簡単ですが、mysql はそれをサポートしていません。

ソースリストを s というテーブルに配置した場合、次を使用できます。

select *
from t
where t.source in (select source from s) and
      t.value in (select value
                  from s join
                       t
                       on t.source = s.source cross join
                       (select count(*) as cnt from s) const
                  group by value
                  having count(distinct t.source) = max(const.cnt)
                 )
于 2012-08-15T17:48:24.140 に答える