2016-11-04 6 views
0

DATAMySQL MANY to ONE JOIN。最悪(最低)結果と最新結果の両方を見つける方法

だから、私は次の形式でのデータのセットを持っている私は、など私はスピードのために車をテストしていたアプリケーション、性能、安全性、 を持って言うことができます:

CAR TABLE 
ID CAR_NAME 
1 Ford Focus 2006 
2 Toyota Corolla 2014 
5 Tesla Model S 2016 

TEST TABLE 
ID TEST_NAME 
1 acceleration 
2 topSpeed 
3 zeroToSixty 
4 smoothRide 
5 seating 
6 ergonomics 
7 handling 
8 breaking 
9 audio 

TEST_CATEGORY TABLE 
ID CATEGORY_NAME 
1 Speed 
2 Performance 
3 Comfort 
4 Safety 

TEST_PLAN TABLE 
ID CAR_ID CATEGORY_ID TEST_ID 
1 1  1   1  
2 1  1   2  
3 1  1   3  
4 1  2   1  
5 1  2   3  
6 1  2   8  
7 1  2   7  
8 1  4   8  
9 1  4   5  
11 5  1   1  
12 5  1   2  
13 5  1   3  
14 5  1   7  
15 5  2   1  
16 5  2   7  
17 5  2   4  
18 5  3   4  
19 5  3   5  

TEST_INSTANCE TABLE 
ID CAR_ID TEST_ID CATEGORY_ID GRADE TEST_DATE 
1 1  1  1   C  2015-03-14 
2 1  1  1   C  2015-03-17 
3 1  1  2   D  2015-03-15 
4 1  1  2   C  2015-03-16 
5 1  1  2   B  2015-03-17 
6 1  3  1   B  2015-03-14 
7 1  3  1   C  2015-03-16 
8 1  8  2   C  2015-03-13 
9 5  1  1   B  2015-03-15 
10 5  1  1   B  2015-03-17 
11 5  1  2   A  2015-03-19 
12 5  1  2   A  2015-03-12 
13 5  7  2   B  2015-03-14 
14 5  7  2   B  2015-03-16 
15 5  7  2   A  2015-03-18 
16 5  7  2   B  2015-03-15 
17 5  9  5   A  2015-03-14 --note that this test is not part of the test plan 

5つのテーブルがありますが、最後の2つ(TEST_PLAN、TEST_INSTANCE)だけが重要です。残りはJOINの依存関係です。

TEST_PLAN表

TEST_PLANテーブルは、各かごに対して実施される必要がある一連のテストを定義します。各テストは複数のカテゴリに分類できます。 TEST_PLANテーブルには、どのテストを実施する必要があるか、どのカテゴリに含まれているかが示されます。スピードカテゴリの下での加速試験は、実行中の加速試験にはカウントされません。

The test plans look a bit like this: 
Ford Focus 2006 
    Speed 
     acceleration 
     topSpeed 
     zeroToSixty 
    Performance 
     acceleration 
     zeroToSixty 
     breaking 
     handling 
    Safety 
     breaking 
     seating 

Tesla Model S 2016 
    Speed 
     acceleration 
     topSpeed 
     zeroToSixty 
     handling 
    Performance 
     acceleration 
     handling 
     smoothRide 
    Comfort 
     smoothRide 
     seating 

TEST_INSTANCE表(カテゴリ下)試験が実施されており

TEST_INSTANCEテーブルトラック。与えられたテストカテゴリは、与えられた車に対して2回以上実施されているかもしれない。テストプランがないテストも実施されている可能性があります。私は凝集を含むいくつかのことを行う必要があり

何をしようとしている

The TEST_INSTANCE table (all JOINed up) looks like this: 
ID CAR     TEST_NAME  TEST_CATEGORY GRADE TEST_DATE 
1 Ford Focus 2006  acceleration Speed   C  2015-03-14 
2 Ford Focus 2006  acceleration Speed   C  2015-03-17 
3 Ford Focus 2006  acceleration Performance  D  2015-03-15 
4 Ford Focus 2006  acceleration Performance  C  2015-03-16 
5 Ford Focus 2006  acceleration Performance  B  2015-03-17 
6 Ford Focus 2006  zeroToSixty  Speed   B  2015-03-14 
7 Ford Focus 2006  zeroToSixty  Speed   C  2015-03-16 
8 Ford Focus 2006  breaking  Performance  C  2015-03-13 
9 Tesla Model S 2016 acceleration Speed   B  2015-03-17 
10 Tesla Model S 2016 acceleration Speed   B  2015-03-15 
11 Tesla Model S 2016 acceleration Performance  A  2015-03-16 
12 Tesla Model S 2016 acceleration Performance  A  2015-03-14 
13 Tesla Model S 2016 handling  Performance  B  2015-03-19 
14 Tesla Model S 2016 handling  Performance  B  2015-03-12 
15 Tesla Model S 2016 handling  Performance  A  2015-03-13 
16 Tesla Model S 2016 handling  Performance  B  2015-03-18 
17 Tesla Model S 2016 zeroToSisty  Speed   A  2015-03-14 --note that this test is not part of the test plan 

  1. 日与えられたテストが与えられたカテゴリ内の最初の走行だった:私は(単一車用)指定されたテスト計画のすべてのテストのリストを取得し、テスト・インスタンスからfolloingに参加しようとしています。

  2. 特定のテストがカテゴリで実行された最新の日付。

  3. テストが特定のカテゴリで実行された回数の合計。与えられたテスト・カテゴリの与えられたテストカテゴリ

  4. 最新の結果について

  5. 最悪の結果。

私は次のクエリを使用していますが、私は1-4の取得方法を理解しました。私はまだ5上のトラブルを抱えている:

SELECT 
    tp.id, 
    c.car_name 
    tc.category_name, 
    t.test_name, 
    MIN(ti.test_date) as firstRun,  -- this grabs the date of the first time the test-category ran 
    MAX(ti.test_date) as latest,   -- this grabs the latest date the test-category ran 
    MIN(ti.grade) as worst,    -- this grabs the worst result fron the test-category 
    COUNT(ti.test_date) as testRuns,  -- this grabs the total number of tests run from the category. 
    ti.grade as latestGrade    -- this seems to give me the most recent grade from a test-category, but I can't be sure. 
FROM 
    testPlan tp 
    LEFT JOIN car c ON c.id = tp.car_id 
    LEFT JOIN test_category tc ON tc.id = tp.category_id 
    LEFT JOIN test t ON t.id = tp.test_id 
    LEFT JOIN test_instance ti ON (
     ti.car_id = tp.car_id 
     AND ti.category_id = tp.category_id 
     AND ti.test_id = tp.test_id 
    ) 
WHERE 
    tp.car_id = 5 
GROUP BY 
    tp.id; 

項目番号5の場合、ti.grade as latestGradeは私に与えられたテストカテゴリの最新のグレードを与えているようだが、私はそれが保証されている方法はありません。私はある種のORDER BYが必要だと思う。

期待値

The final query should return something like this: 
ID CAR    TEST_CATEGORY  TEST_NAME  FIRST_RUN LATEST  TESTS_RUN LATEST_GRADE WORST_GRADE 
11 Tesla Model S Speed    acceleration 2015-03-15 2015-03-17 2   B    B 
12 Tesla Model S Speed    topSpeed  NULL  NULL  0   NULL   NULL 
13 Tesla Model S Speed    zeroToSixty  NULL  NULL  0   NULL   NULL 
14 Tesla Model S Speed    handling  NULL  NULL  0   NULL   NULL 
15 Tesla Model S Performance   acceleration 2015-03-14 2015-03-16 2   A    A 
16 Tesla Model S Performance   handling  2015-03-12 2015-03-19 4   A    B 
17 Tesla Model S Performance   smoothRide  NULL  NULL  0   NULL   NULL 
18 Tesla Model S Comfort    smoothRide  NULL  NULL  0   NULL   NULL 
19 Tesla Model S Comfort    seating   NULL  NULL  0   NULL   NULL 

Resultset Note: 
- there should be only one row per each test-category in the test plan (per car). (9 items in Tesla S test plan). 

  1. は私がlatestGradeが常に最新になることを保証するために、クエリに追加する必要がありますQUESTION?
  2. UNION ALLは、計画外の結果に参加するとパフォーマンスが低下しますか? (私の実際のデータセットは10k +レコードが返されます)。 UNION ALLが不要なようにクエリをリファクタリングする方法はありますか?
+0

グレード別にグレードを選択すると、グレード – Strawberry

+0

のmy_tableからMax(TEST_DATE)までです。私は理解していません。私の 'GROUP BY'に' GROUP BY grade'を追加することを提案していますか?私の結果セットには、テスト計画エントリごとに1つの行が必要です。グループを追加すると、グループが追加されます。 – mcmurphy

+0

1-4は、単純な 'MIN()'と 'MAX()'をカテゴリーごとにグループ化して使用することができます。 5は、http://stackoverflow.com/questions/7745609/sql-select-only-rows-with-max-value-on-a-column?rq=1のクエリのようなクエリに参加する必要があります。 – Barmar

答えて

1

1-4を取得するために使用する、この "シンプル" クエリと最新のグレードのための最高のID:テストデータ用

SELECT ti.car_id, ti.category_id, ti.test_id, 
    MIN(ti.test_date) as firstRun, 
    MAX(ti.test_date) as latest, 
    MIN(ti.grade) as worst, 
    COUNT(ti.test_date) as testRuns, 
    MAX(ti.ID) as max_id -- use later to get latest grade 
FROM test_instance ti 
GROUP BY ti.car_id, ti.category_id, ti.test_id 

結果:

| CAR_ID | CATEGORY_ID | TEST_ID | firstRun |  latest | worst | testRuns | max_id | 
|--------|-------------|---------|------------|------------|-------|----------|--------| 
|  1 |   1 |  1 | 2015-03-14 | 2015-03-17 |  C |  2 |  2 | 
|  1 |   1 |  3 | 2015-03-14 | 2015-03-16 |  B |  2 |  7 | 
|  1 |   2 |  1 | 2015-03-15 | 2015-03-17 |  B |  3 |  5 | 
|  1 |   2 |  8 | 2015-03-13 | 2015-03-13 |  C |  1 |  8 | 
|  5 |   1 |  1 | 2015-03-15 | 2015-03-17 |  B |  2 |  10 | 
|  5 |   2 |  1 | 2015-03-12 | 2015-03-19 |  A |  2 |  12 | 
|  5 |   2 |  7 | 2015-03-14 | 2015-03-18 |  A |  4 |  16 | 
|  5 |   5 |  9 | 2015-03-14 | 2015-03-14 |  A |  1 |  17 | 

http://sqlfiddle.com/#!9/6df83/4

他のテーブルと結果を結合する:

SELECT sub.firstRun, sub.latest, sub.worst, sub.testRuns, 
    ti.grade as latestGrade, 
    c.car_name, 
    tc.category_name, 
    t.test_name, 
    tp.id as test_plan_id 
FROM (
    SELECT ti.car_id, ti.category_id, ti.test_id, 
     MIN(ti.test_date) as firstRun, 
     MAX(ti.test_date) as latest, 
     MIN(ti.grade) as worst, 
     COUNT(ti.test_date) as testRuns, 
     MAX(ti.ID) as max_id -- use later to get latest grade 
    FROM test_instance ti 
    GROUP BY ti.car_id, ti.category_id, ti.test_id 
) sub 
JOIN test_instance ti ON ti.id = sub.max_id 
JOIN car c   ON c.id = sub.car_id 
JOIN test_category tc ON tc.id = sub.category_id 
JOIN test t   ON t.id = sub.test_id 
LEFT JOIN test_plan tp 
    ON tp.car_id  = sub.car_id 
    AND tp.category_id = sub.category_id 
    AND tp.test_id  = sub.test_id 

結果:

| firstRun |  latest | worst | testRuns | latestGrade |   CAR_NAME | CATEGORY_NAME | TEST_NAME | test_plan_id | 
|------------|------------|-------|----------|-------------|--------------------|---------------|--------------|--------------| 
| 2015-03-14 | 2015-03-17 |  C |  2 |   C | Ford Focus 2006 |   Speed | acceleration |   1 | 
| 2015-03-14 | 2015-03-16 |  B |  2 |   C | Ford Focus 2006 |   Speed | zeroToSixty |   3 | 
| 2015-03-15 | 2015-03-17 |  B |  3 |   B | Ford Focus 2006 | Performance | acceleration |   4 | 
| 2015-03-13 | 2015-03-13 |  C |  1 |   C | Ford Focus 2006 | Performance |  breaking |   6 | 
| 2015-03-15 | 2015-03-17 |  B |  2 |   B | Tesla Model S 2016 |   Speed | acceleration |   11 | 
| 2015-03-12 | 2015-03-19 |  A |  2 |   A | Tesla Model S 2016 | Performance | acceleration |   15 | 
| 2015-03-14 | 2015-03-18 |  A |  4 |   B | Tesla Model S 2016 | Performance |  handling |   16 | 

http://sqlfiddle.com/#!9/6df83/5

テストでは、テスト計画、test_plan_id "の部分は" NULLになりますされていない場合。

その列と最後のJOINを削除できるように、test_plan_idが必要ない場合もあります。

+0

+1クールなサブクエリです。それは役に立ちました。メインクエリで返される結果が多すぎます。私はtest_planテーブル内の項目ごとに1行だけを返そうとしています。私は、私が到達しようとしている結果セットを追加するための質問を編集しました。 – mcmurphy

+0

また、テストプランのテストからデータを取得する場合にのみ焦点を当てるようにしました。私が必要ならUNION_ALLに関する別の質問をします。 – mcmurphy

+0

カテーテルごとに複数の検査があります。カテゴリごとに1行が必要な場合、 'test_name'を選択しますか? –

関連する問題