0

MySQL に 2 つのテーブルがあり、次の属性と比較しています。

tbl_fac : facility_id, chemical_id, criteria
             10      , 25         , 50
             10      , 26         , 60
             10      , 27         , 60
             11      , 25         , 30
             11      , 27         , 31 
              etc...

tbl_samp: sample_id, chemical_id, result
            5     ,    25         , 51
            5     ,    26         , 61
            6     ,    25         , 51
            6     ,    26         , 61
            6     ,    27         , 500

              etc.... 

これらのテーブルは Chemical_id (多対多---- うーん) で結合され、数千の facility_id と、各施設 ID に対して数百のchemical_id があります。また、数千の sample_id があり、それぞれが各 sample_id に対して数百の Chemical_id を持っています。全体として、tbl_fac には約 500,000 のレコードがあり、tbl_samp には 1,000,000 以上のレコードがあります。

このデータセットから sample_id の 3 つのグループを抽出しようとしています。

グループ 1: tbl_samp.result > tbl_fac.criteria (つまり、結果が基準を超える) の任意の sample_id

グループ 2: tbl_samp.result < tbl_fac.criteria の任意の sample_id であり、かつすべての tbl_fac.chemical_id がその sample_id に対して存在する (すなわち、結果が基準未満であり、すべてがそこにある)

グループ 3: tbl_samp.result < tbl_fac.criteria である任意の sample_id、しかし sample_id で 1 つ以上の tbl_fac.chemical_id が欠落している (つまり、結果は基準よりも小さいが、何かが欠落している)

質問は次のとおりです。3 つのグループすべてを 1 つのクエリで効率的に取得するにはどうすればよいですか?

私はもう試した:

select * 
from tbl_fac 
left join tbl_samp 
    on tbl_fac.chemical_id = tbl_samp.chemical_id

ただし、これはデータセット全体 (個々のサンプルではなく) に欠落している値のみを生成します。私は tbl_fac と tbl_samp を結合するために 3 番目のテーブルを使用するハック クエリを実行していますが、それは非常に醜いので、実際に投稿するのは恥ずかしいです....

いつものように、これについてのご意見をお寄せいただきありがとうございます。

乾杯、

ジョシュ

編集:理想的には、sample_id と Group が返されることを望んでいます。サンプル ID ごとに 1 つの Group のみが返されます (データに関する私の知識では、それらは常に上記の 3 つのカテゴリのいずれかに分類されることが示されています)。

4

2 に答える 2

1
SELECT
    sample_id,
    IF(result = criteria, -1,  /* unspecified behavior */
     IF(result > criteria, 1,
      IF(nb_chemicals = total_nb_chemicals, 2, 3))) AS grp

FROM (
    SELECT s.result, s.sample_id, f.criteria, f.chemical_id,
        COUNT(DISTINCT f.chemical_id) AS nb_chemicals
    FROM tbl_fac f JOIN tbl_samp s
        ON f.chemical_id = s.chemical_id
    GROUP BY s.sample_id
) t 

CROSS JOIN (
    SELECT COUNT(DISTINCT chemical_id) AS total_nb_chemicals
    FROM tbl_fac
) u

新しいソリューション:

SELECT
    s.sample_id,
    IF(s.result = f.criteria, -1,  /* unspecified behavior */
     IF(s.result > f.criteria, 1,
      IF(sample_nb_chemicals = total_nb_chemicals, 2, 3))) AS grp

FROM
    tbl_fac f JOIN tbl_samp s
    ON f.chemical_id = s.chemical_id

    JOIN (
        SELECT s.sample_id, 
               COUNT(DISTINCT f.chemical_id) AS sample_nb_chemicals
        FROM tbl_fac f JOIN tbl_samp s
             ON f.chemical_id = s.chemical_id
        GROUP BY s.sample_id
    ) u
       ON s.sample_id = u.sample_id

    CROSS JOIN (
        SELECT COUNT(DISTINCT chemical_id) AS total_nb_chemicals
        FROM tbl_fac
    ) v

GROUP BY sample_id, grp
于 2012-03-06T08:51:04.167 に答える