3

エグゼクティブ サマリー: SQL ANSI-89 で作成されたクエリは、SQL ANSI-92 を使用するデータベースに転送する必要があります。外部結合が関係しています。


ANSI-89 クエリを実行しています

必要に応じてテーブル構造を示すことができますが、基本的な考え方は、従業員のテーブル、オンライン コースのテーブル、および従業員 ID、コース ID、および合格/不合格の指標として使用している評価列。

キー列のテーブル スタイルは、主キーが常に「id」であり、外部キーが常に「tablename _id」であるというものです。

select の ANSI-89 (MySQL 4.1.14) バージョンは次のとおりです。

SELECT E.id,
   E.firstname, E.surname, E.suffix,
   sum( if( ECT.rating =1, 1, 0 ) ) AS passcount,
   sum( if( ECT.rating =0, 1, 0 ) ) AS retakecount,
   sum( if( ECT.rating IS NULL , 1, 0 ) ) AS totakecount,
   L.locationname
FROM employee E,
   location L
INNER JOIN emplcoursetaken ECT ON E.id = ECT.employee_id
RIGHT JOIN courses C ON C.id = ECT.course_id
WHERE C.linkready =1
AND E.location_id = L.id
GROUP BY E.id
ORDER BY L.locationname, E.surname, E.firstname;

そして、それは機能します。次のような素敵な行のセットを取得します。

620 Johnny  Test        12  0   14  Chicago

ジョニーは 26 コースのうち 12 コースを受講し、その 12 コースに合格しました。

しかし、このクエリを ANSI-92 (MySQL 5.1.55) に移行するのに問題があります。

SELECT E.id,
   E.firstname, E.surname, E.suffix,
   sum( if( ECT.rating =1, 1, 0 ) ) AS passcount,
   sum( if( ECT.rating =0, 1, 0 ) ) AS retakecount,
   sum( if( ECT.rating IS NULL , 1, 0 ) ) AS totakecount,
   L.locationname
FROM employee E
INNER JOIN emplcoursetaken ECT ON E.id = ECT.employee_id
RIGHT JOIN courses C ON C.id = ECT.course_id
INNER JOIN location L ON E.location_id = L.id
WHERE C.linkready =1
GROUP BY E.id
ORDER BY L.locationname, E.surname, E.firstname;

このデータベースのコース テーブルには 9 つのコースしかないため、ゼロ以外の別の「totakecount」値を取得する必要があります。

620 Johnny  Test    NULL    1   0   0   Chicago 

totakecount 列に「8」があるはずです。代わりにゼロがあります。実験として、「RIGHT」を「INNER」に変更しましたが、同じ結果が得られました。したがって、明らかに構文に問題がありますが、Web 検索では何がわかりません。

ありがとう。

4

2 に答える 2

0

元のクエリが ANSI 89 であるかどうかはわかりません。ただし、 を として使用し,ていcross joinます。クロス結合に置き換えるだけです:

SELECT E.id,
   E.firstname, E.surname, E.suffix,
   sum( if( ECT.rating =1, 1, 0 ) ) AS passcount,
   sum( if( ECT.rating =0, 1, 0 ) ) AS retakecount,
   sum( if( ECT.rating IS NULL , 1, 0 ) ) AS totakecount,
   L.locationname
FROM employee E cross join
   location L
INNER JOIN emplcoursetaken ECT ON E.id = ECT.employee_id
RIGHT JOIN courses C ON C.id = ECT.course_id
WHERE C.linkready =1
AND E.location_id = L.id
GROUP BY E.id
ORDER BY L.locationname, E.surname, E.firstname;

見た目から、クロス結合を内部結合に変換できます。

SELECT E.id,
   E.firstname, E.surname, E.suffix,
   sum( if( ECT.rating =1, 1, 0 ) ) AS passcount,
   sum( if( ECT.rating =0, 1, 0 ) ) AS retakecount,
   sum( if( ECT.rating IS NULL , 1, 0 ) ) AS totakecount,
   L.locationname
FROM employee E join
   location L
   on E.location_id = L.id
INNER JOIN emplcoursetaken ECT ON E.id = ECT.employee_id
RIGHT JOIN courses C ON C.id = ECT.course_id
WHERE C.linkready =1
GROUP BY E.id
ORDER BY L.locationname, E.surname, E.firstname;

あなたのコメントは興味深いです。私はcross join,が意味的に同一であると考えました。これは歴史的には当てはまりますが、現在はそうではありません (ここで説明されているように):

以前は、コンマ演算子 (,) と JOIN はどちらも同じ優先順位を持っていたため、結合式 t1, t2 JOIN t3 は ((t1, t2) JOIN t3) と解釈されていました。現在、JOIN の優先順位が高いため、式は (t1, (t2 JOIN t3)) として解釈されます。この変更は、ON 句を使用するステートメントに影響します。これは、ON 句が結合のオペランド内の列のみを参照できるためであり、優先順位の変更により、これらのオペランドの解釈が変更されるためです。

この場合は、括弧で優先順位の問題を解決する必要があります。

FROM (employee E cross join
      location L
     ) el
    INNER JOIN emplcoursetaken ECT ON El.id = ECT.employee_id

唯一の問題はエイリアシングの問題です。. . に変更する必要がある場合がありますel

于 2013-04-29T23:52:25.810 に答える