2012-03-06 7 views
0

私は次の属性と比較してるMySQLで2つのテーブルを持っていることで行方不明:MySQLの>、<、およびグループ

これらのテーブル

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(によって結合されている多対多--- 〜ugh)、facility_idには数千のchemical_idがあり、各facility_idには数百のchemical_idがあります。数千のsample_idも存在し、各sample_idにはそれぞれ数百のchemical_idがあります。オールインオールで、tbl_facには約500,000レコード、tbl_sampには1,000,000+レコードがあります。

私は、このデータセットからsample_id年代の三つのグループを抽出しようとしている:

グループ1:任意のsample_id tbl_samp.result> tbl_fac.criteria(すなわち、結果が基準を超えている)

グループ2:任意のsample_idどこtbl_samp.result < tbl_fac.criteria、およびすべてのtbl_fac.chemical_idさんは、そのsample_idのために存在している(つまり、結果が基準未満であり、すべてがそこにある)

グループ3:tbl_samp.result < tbl_fac任意の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番目のテーブルを使用してハッキーなクエリの作業をしていますが、それはとても醜いです。私は実際にそれを投稿するために恥ずかしいです。...

いつものように、 1!

乾杯、

ジョシュ

EDIT:理想的には、私はsample_idを希望し、グループが返される - サンプルIDごとに1つのグループで(データの私の知識は、彼らが常に落ちることを示しています上記の3つのカテゴリのいずれかに)。

+0

あなたは返さ何をしたいですか? 'sample_id'と何らかの' group_it_belongs_to'列のテーブル? –

+0

まあまあです。あなたのコメントを反映するように更新しました。ありがとう! – Josh

答えて

1

この回答はtbl_facfacility_idchemical_id上で一意制約とtbl_sampsample_idchemical_id上で一意制約があることが前提になります。私がやったのは、一度に1ステップずつクエリを構築することでした。これが効率的かどうかはまだ分かりません。

グループ1:任意のsample_id tbl_samp.result> tbl_fac.criteria(すなわち、結果が基準を超えている)

SELECT tbl_samp.sample_id, 
     'ResultsGreaterThanCriteria' AS samplegroup 
FROM tbl_fac 
     INNER JOIN tbl_samp 
     ON tbl_fac.chemical_id = tbl_samp.chemical_id 
WHERE tbl_samp.result > tbl_fac.criteria 
GROUP BY tbl_samp.sample_id 

グループ2:tbl_samp.result < tbl_fac.criteria、およびすべてのtbl_fac.chemical_id年代任意のsample_idそのsample_idのために存在している(つまり、結果が基準未満であり、すべてがそこにある)

SELECT tbl_samp.sample_id, 
     'ResultLessThanCriteriaAndAllChems' AS samplegroup 
FROM tbl_fac 
     INNER JOIN tbl_samp 
     ON tbl_fac.chemical_id = tbl_samp.chemical_id 
WHERE tbl_samp.result < tbl_fac.criteria 
     AND NOT EXISTS (SELECT * 
         FROM tbl_fac tf 
           LEFT JOIN tbl_samp ts 
           ON tf.chemical_id = ts.chemical_id 
         WHERE ts.chemical_id IS NULL 
           AND tbl_samp.sample_id = ts.sample_id) 
GROUP BY tbl_samp.sample_id 

グループ3:任意のsample_id tbl_samp.result < tbl_fac。基準が、1つ以上のtbl_fac.chemical_id年代はsample_idに欠けている(つまり、結果が基準に満たないが、何かが欠けている)

SELECT tbl_samp.sample_id, 
     'ResultsLessThanCriteriaWithMissingChems' AS samplegroup 
FROM tbl_fac 
     INNER JOIN tbl_samp 
     ON tbl_fac.chemical_id = tbl_samp.chemical_id 
WHERE tbl_samp.result < tbl_fac.criteria 
     AND EXISTS (SELECT * 
        FROM tbl_fac tf 
          LEFT JOIN tbl_samp ts 
          ON tf.chemical_id = ts.chemical_id 
        WHERE ts.chemical_id IS NULL 
          AND tbl_samp.sample_id = ts.sample_id) 
GROUP BY tbl_samp.sample_id 

そして最後に、あなたは労働組合、3つのすべてのクエリ一緒に取得する:

SELECT tbl_samp.sample_id, 
     'ResultsGreaterThanCriteria' AS samplegroup 
FROM tbl_fac 
     INNER JOIN tbl_samp 
     ON tbl_fac.chemical_id = tbl_samp.chemical_id 
WHERE tbl_samp.result > tbl_fac.criteria 
GROUP BY tbl_samp.sample_id 
UNION ALL 
SELECT tbl_samp.sample_id, 
     'ResultLessThanCriteriaAndAllChems' AS samplegroup 
FROM tbl_fac 
     INNER JOIN tbl_samp 
     ON tbl_fac.chemical_id = tbl_samp.chemical_id 
WHERE tbl_samp.result < tbl_fac.criteria 
     AND NOT EXISTS (SELECT * 
         FROM tbl_fac tf 
           LEFT JOIN tbl_samp ts 
           ON tf.chemical_id = ts.chemical_id 
         WHERE ts.chemical_id IS NULL 
           AND tbl_samp.sample_id = ts.sample_id) 
GROUP BY tbl_samp.sample_id 
UNION ALL 
SELECT tbl_samp.sample_id, 
     'ResultsLessThanCriteriaWithMissingChems' AS samplegroup 
FROM tbl_fac 
     INNER JOIN tbl_samp 
     ON tbl_fac.chemical_id = tbl_samp.chemical_id 
WHERE tbl_samp.result < tbl_fac.criteria 
     AND EXISTS (SELECT * 
        FROM tbl_fac tf 
          LEFT JOIN tbl_samp ts 
          ON tf.chemical_id = ts.chemical_id 
        WHERE ts.chemical_id IS NULL 
          AND tbl_samp.sample_id = ts.sample_id) 
GROUP BY tbl_samp.sample_id 
+0

私は** facility_idまたはsample_idを与えるためにchemical_idの重複があるいくつかのインスタンスを持っているかもしれませんが、ここであなたはこれを見ています。入力いただきありがとうございます!素晴らしく見える! – Josh

+0

これは非常に非常に近いです。 "ResultLessThanCriteriaAndAllChems"グループはまず、tbl_facとtbl_sampをchemical_idでリンクし、結果 Josh

+0

"ResultLessThanCriteriaAndAllChems"という結果は得られません。何かご意見は? – Josh

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 
+0

応答ありがとう!今すぐ行く。 – Josh

+0

このクエリの中心にあるネストされたクエリは、各sample_idに対して1つの結果しか返さないと思います。実際には、各単一の結果を各条件と比較して、与えられたsample_idについて、sample_idがGroup_1、Group_2、またはGroup_3属性を持つかどうかをチェックする必要があります。つまり、あなたのクエリは非常に高速ですが、ネストされたクエリグループ関数から返された最初の結果(それが何であれ)を解析するだけです。これは正確に私がこれを理解しようとしていた時の問題です!何かご意見は? – Josh

+0

はい、そうです。私はsample_idの3つのグループが互いに排他的であることが分かっていたと思います。これは、各sample_idに対して1つの化学物質/結果/基準のコンボを見るだけでよいことを意味します。そうでない場合には、それを動作させる方法について考えてみましょう。 – mwhite

関連する問題